2011-05-24 105 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