Django:完整性错误,唯一约束失败:user_profile.user_id

24

当我尝试编辑一个用户配置文件(UserProfile)以添加信息时,我遇到了这个奇怪的错误:

IntegrityError at /profiles/edit/
UNIQUE constraint failed: user_profile.user_id

这里有什么问题,

模型:

class UserProfile(models.Model):

    user = models.OneToOneField(User)
    bio = models.TextField(blank=True)
    phone= models.CharField(max_length=10, blank=True)
    address = models.CharField(max_length=1024)
    age = models.PositiveIntegerField(blank=True,null=True)
    gender = models.IntegerField(choices=GENDER_CHOICES, default=1)

表格:

class UserProfileForm(forms.ModelForm):

    class Meta:
        model = UserProfile
        fields = ('phone','age','gender','address','bio')

视图:

def edit_profile(request):

    if request.method == 'POST':
        form = UserProfileForm(request.POST)
        print request.POST
        if form.is_valid():

            new_profile = UserProfile(
                            user = request.user,
                            bio = request.POST['bio'],
                            address = request.POST['address'],
                            age = request.POST['age']
                            )

            new_profile.save()

            return HttpResponseRedirect(reverse('user_public_profile', args=(request.user.username,)))
        return render(request,'users/edit_profile.html', {'form': form})

    else:
        form = UserProfileForm()
        return render(request,'users/edit_profile.html',
                          {'form': form})

虽然与您的问题无关,但我在意外更改 ModelForm.save(commit=False) 上的对象字段时遇到了相同的错误,或者至少与我处理 commit 的方式有关。 - jozxyqk
6个回答

30

这并不奇怪。您已经为该用户创建了一个档案,因此添加另一个档案会破坏唯一约束条件。 您需要编辑现有的档案,而不是添加新的。

还要注意,当您保存数据时,您没有使用已清理的表单数据,而您应该使用它。 要么使用 form.cleaned_data['bio'] 等,或者更好的方法是只需使用 form.save(),这是使用模型表单的主要目的。

将它们结合起来:

try:
    profile = request.user.userprofile
except UserProfile.DoesNotExist:
    profile = UserProfile(user=request.user)

if request.method == 'POST':
    form = UserProfileForm(request.POST, instance=profile)
    if form.is_valid():
        form.save()
        return redirect...
else:
    form = UserProfileForm(instance=profile)
return render...

9
我曾多次遇到同样的错误,一度感到沮丧,但最终找到了解决方案。
转换为:

我曾经多次遇到相同的错误,一直感到灰心丧气,但最终找到了解决方案。

user = models.OneToOneField(User)

to

user = models.ForeignKey(User)

这将解决问题。

1
但如果有人需要OneToOneFields,那么这将是一个错误的想法。 - Sandeep Agrawal
这对我有用,但尝试注册用户时,我收到了“User”对象没有属性“profile”的错误。我该如何解决? - Abayomi Olowu
@elderlee,您可以设置related_name="user"来使用profile.user。 - Shubham Gupta - TCH
救了我的一天,伙计 <3 - codingbruh
添加 related_name = "user" 实际上并不理想,因为在尝试进行筛选时会带来更多的错误。我所做的只是删除迁移,然后将 user = models.Foreignkey(User) 进行迁移和迁移,然后将其改回 user = models.OneToOneField(User),再次进行迁移和迁移,一切都正常工作了。 - Abayomi Olowu
1
我认为你应该将 ForiegnKey 编辑为 ForeignKey。这可能会让初学者感到困惑。 - Stanley Ulili

2
考虑这种情况:如果同一用户再次在URL“profile/edit”上进行POST请求,则您的代码将尝试使用相同的用户实例创建新的UserProfile,但由于这是一个一对一字段,并且您已经使用该用户创建了一个配置文件,因此它会抛出完整性错误。
因此,您应该首先检查与该用户关联的配置文件是否已经存在,如果不存在,则创建它。

这是解决问题的正确方法,而不是将OneToOne转换为ForeignKey - netcyrax

0

我不小心遇到了这个错误,因为我在调用save时忘记指定update_fields。我的代码是:

modified_instance.save(video_attr)

当我应该有:

modified_instance.save(update_fields=[video_attr])

这个 truthy 字符串被解释为定位的 force_update 参数,如果记录已经存在,这显然会引起问题。


0
在UserProfileForm(request.POST)中添加(instance=request.user)。

1
欢迎来到stackoverflow。从您的帖子中并不清楚应该添加哪些代码到哪里。一些额外的解释也会有所帮助。 - tobltobs

-2

是的,您正在 User 和 UserProfile 模型之间建立 OneToOne 关系,这就是为令您面临完整性错误的原因, 要解决此问题,您可以将其更改为 ForeignKey 例如:

class UserProfile(models.Model):

user = models.ForeignKey(User,on_delete=models.CASCADE)
bio = models.TextField(blank=True)
...
...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接