2011-05-24 16 views
9

मेरे मॉडल:Django - व्यवस्थापक में UserProfile M2M क्षेत्र - त्रुटि

class UserProfile(models.Model): 
    TYPES_CHOICES = (
     (0, _(u'teacher')), 
     (1, _(u'student')), 
    ) 
    user = models.ForeignKey(User, unique=True) 
    type = models.SmallIntegerField(default=0, choices=TYPES_CHOICES, db_index=True) 
    cities = models.ManyToManyField(City) 
class City(models.Model): 
    name = models.CharField(max_length=50) 
    slug = models.SlugField(max_length=50) 

admin.py में:

admin.site.unregister(User) 
class UserProfileInline(admin.StackedInline): 
    model = UserProfile 

class UserProfileAdmin(UserAdmin): 
    inlines = [UserProfileInline] 

admin.site.register(User, UserProfileAdmin) 

@receiver(post_save, sender=User) 
def create_profile(sender, instance, created, **kwargs): 
    """Create a matching profile whenever a user object is created.""" 
    if created: 
     profile, new = UserProfile.objects.get_or_create(user=instance) 

लेकिन जब मैं नए उपयोगकर्ता को जोड़ने और एक शहर का चयन मुझे लगता है कि त्रुटि मिलती है: IntegrityError कुंजी/user/auth/user/add/ (1062, कुंजी 'user_id' के लिए "डुप्लिकेट एंट्री '3')

मेरे कोड में क्या गलत है? अगर मैं किसी भी शहर का चयन नहीं करता - उपयोगकर्ता ठीक से जोड़ा जाता है। कुछ तरीकों से, उपयोगकर्ता को एक से अधिक बार UserProfile में जोड़ा जा रहा है।

उत्तर

20

मुझे हाल ही में यही समस्या थी। जब आप इसके बारे में सोचते हैं तो यह वास्तव में सही समझ में आता है। जब आप व्यवस्थापक में इनलाइन के साथ एक फॉर्म सहेजते हैं, तो यह मुख्य मॉडल को पहले सहेजता है, और फिर प्रत्येक इनलाइन को सहेजने के लिए आगे बढ़ता है। जब यह मॉडल को सहेजता है, तो आपका पोस्ट_सेव सिग्नल निकाल दिया जाता है और उपयोगकर्ता प्रोफाइल बनाने के लिए बनाया जाता है, लेकिन अब इनलाइनों को सहेजने का समय है। UserProfile इनलाइन को नया माना जाता है, क्योंकि यह पहले अस्तित्व में नहीं था (इसमें कोई पीके मान नहीं है), इसलिए यह पूरी तरह से नए और अलग उपयोगकर्ता प्रोफाइल के रूप में सहेजने का प्रयास करता है और आपको अद्वितीय बाधा का उल्लंघन करने के लिए उस अखंडता त्रुटि मिलती है। समाधान सरल है। बस UserProfile.save ओवरराइड:

def save(self, *args, **kwargs): 
    if not self.pk: 
     try: 
      p = UserProfile.objects.get(user=self.user) 
      self.pk = p.pk 
     except UserProfile.DoesNotExist: 
      pass 

    super(UserProfile, self).save(*args, **kwargs) 

मूलतः, यह सिर्फ प्रश्न में उपयोगकर्ता के लिए एक मौजूदा UserProfile हो, तो जाँच करता है। यदि ऐसा है, तो यह इस उपयोगकर्ता प्रोफाइल को पीके को सेट करता है ताकि Django एक निर्माण के बजाय अद्यतन करता हो।

+0

धन्यवाद, अब यह काम करता है! यह इतना आसान बीटीडब्ल्यू था: डी – robos85

+0

धन्यवाद! मुझे भी बिल्कुल यही समस्या है। यह समाधान समझ में आता है और पूरी तरह से काम करता है। – adam

+2

उत्कृष्ट रूप से समझाया गया। शायद अतिरिक्त उपयोगकर्ता डेटा संग्रहीत करने पर Django दस्तावेज को इसका उल्लेख करने के लिए अद्यतन किया जाना चाहिए क्योंकि दस्तावेज़ीकरण में प्रस्तुत उदाहरण अन्यथा काम करने में विफल रहेगा। – CadentOrange

संबंधित मुद्दे