9

我的模型:

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)

但是当我添加新用户并选择一个城市时,我得到了这个错误: /admin/auth/user/add/ 的 IntegrityError (1062, "Duplicate entry '3' for key 'user_id'")

我的代码有什么问题?如果我不选择任何城市 - 用户已正确添加。以某种方式,用户被多次添加到 UserProfile 中。

4

1 回答 1

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。如果是这样,它将这个 UserProfile 的 pk 设置为那个,以便 Django 进行更新而不是创建。

于 2011-05-24T22:00:56.977 回答