Django:如何从模型中验证unique_together [英] Django: How do I validate unique_together from within the model

查看:219
本文介绍了Django:如何从模型中验证unique_together的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下内容:

class AccountAdmin(models.Model):

    account = models.ForeignKey(Account)
    is_master = models.BooleanField()
    name = models.CharField(max_length=255)
    email = models.EmailField()

    class Meta:
        unique_together = (('Account', 'is_master'), ('Account', 'username'),)

如果我随后在同一帐户中使用与另一个用户名相同的用户名创建一个新的AccountAdmin,而不是让我在模板中显示错误,它将以IntegrityError中断并且页面消失。我希望在我看来,我可以继续:

If I then create a new AccountAdmin with the same username as another on the same account, instead of it giving me an error to display in the template, it breaks with an IntegrityError and the page dies. I wish that in my view, I could just go:

if new_accountadmin_form.is_valid():
    new_accountadmin_form.save()

我如何克服这个问题。还有第二种 is_valid()类型的方法,用于检查数据库是否违反 unique_together =((''Account','is_master'), (帐户,用户名),)部分?

How do I conquer this problem. Is there a second is_valid() type of method that checks the DB for violation of the unique_together = (('Account', 'is_master'), ('Account', 'username'),) part?

我希望不必在自己的视图中捕获IntegrityError。这是领域逻辑与表示逻辑的混合。它违反了DRY,因为如果我在2页上显示相同的表单,则必须重复相同的代码块。它也违反了DRY,因为如果同一件事情我有两种形式,我必须写相同的东西,除了:再次。

I would like not to have to catch an IntegrityError in my view. That's domain logic mixed with presentation logic. It violates DRY because if I display the same form on 2 pages, I'll have to repeat the same block. It also violates DRY because if I have two forms for the same thing, I have to write the same except: again.

推荐答案

有两种选择:

a)有一个try块,您可以在其中保存模型并捕获IntegrityError并进行处理。像这样的东西:

a) Have a try block where you save your model and capture the IntegrityError and deal with it. Something like:

try:
    new_accountadmin_form.save()
except IntegrityError:
    new_accountadmin_form._errors["account"] = ["some message"]
    new_accountadmin_form._errors["is_master"] = ["some message"]

    del new_accountadmin_form.cleaned_data["account"]
    del new_accountadmin_form.cleaned_data["is_master"]

b)在clean()方法中表单上的内容,请检查该行是否存在并引发带有相应消息的 forms.ValidationError 。示例这里

b) In the clean() method of your form, check if the a row exists and raise a forms.ValidationError with an appropriate message. Example here.

所以,b)是...这就是为什么我引用了文件;

So, b) it is... That is why I referenced the documentation; all you need is there.

但是它会是这样的:

class YouForm(forms.Form):
    # Everything as before.
    ...

    def clean(self):
       """ This is the form's clean method, not a particular field's clean method """
       cleaned_data = self.cleaned_data

       account = cleaned_data.get("account")
       is_master = cleaned_data.get("is_master")
       username = cleaned_data.get("username")

       if AccountAdmin.objects.filter(account=account, is_master=is_master).count() > 0:
           del cleaned_data["account"]
           del cleaned_data["is_master"]
           raise forms.ValidationError("Account and is_master combination already exists.")

       if AccountAdmin.objects.filter(account=account, username=username).count() > 0:
           del cleaned_data["account"]
           del cleaned_data["username"]
           raise forms.ValidationError("Account and username combination already exists.")

    # Always return the full collection of cleaned data.
    return cleaned_data

对于它的价值-我刚刚意识到您上面的unique_together正在引用

For what it is worth - I just realized that your unique_together above is referencing a field called username that is not represented in the model.

上面的clean方法在调用各个字段的所有clean方法之后被调用。

The clean method above is called after all clean methods for the individual fields are called.

这篇关于Django:如何从模型中验证unique_together的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆