2011-05-24 51 views
9

我的模型:Django的 - 在管理用戶配置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 at/admin/auth/user/add/ (1062,「關鍵'user_id'的重複條目'3'))

我的代碼有什麼問題?如果我不選擇任何城市 - 用戶添加正確。某些方面,用戶不止一次被添加到UserProfile。

回答

20

我最近有同樣的問題。當你考慮它時,它確實非常有意義。當您在管理員中使用內聯格式保存表格時,首先保存主模型,然後繼續保存每個內聯格式。當它保存模型時,你的post_save信號將被觸發並創建UserProfile以匹配,但現在是時候保存內聯。 UserProfile內聯被認爲是新的,因爲它以前不存在(沒有pk值),所以它試圖保存爲一個全新的不同的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的pk設置爲那個,以便Django執行更新而不是創建。

+0

謝謝,現在它工作! 這是如此簡單順便說一句:D – robos85 2011-05-24 22:08:45

+0

謝謝!我有同樣的問題。這個解決方案很有意義並且完美。 – adam 2012-02-02 17:52:11

+2

優秀解釋。也許關於存儲額外用戶數據的Django文檔應該更新以提到這一點,因爲文檔中提供的示例將無法正常工作。 – CadentOrange 2012-12-03 09:38:29