使用外键的unique_together django会引发验证错误

时间:2014-05-04 11:40:01

标签: python django

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 个答案:

答案 0 :(得分: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  )

免责声明,未经测试。

PE:检查你的代码,只有在没有通知用户的情况下才能保存实例。