使用外键的unique_together在Django中引发验证错误

1 投票
1 回答
1048 浏览
提问于 2025-04-18 05:18

models.py

class Follow(models.Model):
date_time = models.DateTimeField(auto_now_add=True, blank=True, unique=False)
user = models.ForeignKey(User)
follower = models.ForeignKey(User, related_name="followers", unique=False)

def __unicode__(self):
    return '%s, %s' % (self.user.username, self.follower)

class Meta:
    unique_together = [("user", "follower")]

view.py

def new_follow(request):
if request.method == 'POST':
    form = FollowForm(request.POST)
    if form.is_valid():
        instance = form.save(commit=False)
        if not hasattr(instance, 'user'):
            instance.user = request.user
            instance.save()
            form.save_m2m()
        return HttpResponseRedirect('/followers/' + request.user.username)
    else:
        new_follow()
else:
    form = FollowForm()

args = {}
args.update(csrf(request))
args['form'] = form
variables = RequestContext(request, {'form': form})
return render_to_response('new_follow.html', variables)

forms.py

class FollowForm(forms.ModelForm):

class Meta:
    model = Follow
    exclude = ['user']

我在数据库中已经存在一个关注记录时,出现了这个错误,我该怎么解决呢?在管理面板中,确实会正确地抛出一个错误。

IntegrityError at /follow/
columns user_id, follower_id are not unique

Request Method: POST
Django Version: 1.6
Exception Type: IntegrityError
Exception Value:    
columns user_id, follower_id are not unique

1 个回答

1

也许解决你代码问题的简单方法是,在调用 is_valid() 方法之前,先把用户设置为模型实例。不过,你也可以尝试手动调用 validate_unique

    ...
    instance = form.save(commit=False)
    if not hasattr(instance, 'user'):
        instance.user = request.user
        try:
            instance.validate_unique()
            instance.save()            
            form.save_m2m()
            return HttpResponseRedirect('/followers/' + request.user.username)

        except ValidationError, e:   #<---- Capturing validate unique exception
                                     #      and append error to form error dict
            form._errors = {}
            for _, v in e.message_dict.items():
                form._errors.setdefault(NON_FIELD_ERRORS, []).extend(  v  )

免责声明,这段代码没有经过测试。

另外,检查一下你的代码,只有在用户没有提供的情况下才保存实例,这样做是没有意义的。

撰写回答