Django:如何在模型中验证unique_together

oro*_*aki 2 python django django-models unique-constraint django-views

我有以下内容:

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'),)
Run Code Online (Sandbox Code Playgroud)

如果我然后在同一个帐户上创建一个与另一个用户名相同的新AccountAdmin,而不是让我在模板中显示错误,则会出现IntegrityError,页面就会中断.我希望在我看来,我可以去:

if new_accountadmin_form.is_valid():
    new_accountadmin_form.save()
Run Code Online (Sandbox Code Playgroud)

我该如何克服这个问题.是否有第二种is_valid()类型的方法检查数据库是否违反了该unique_together = (('Account', 'is_master'), ('Account', 'username'),)部分?

我不想在我的视图中捕获IntegrityError.那个域逻辑与表示逻辑混合在一起.它违反DRY,因为如果我在2页上显示相同的表格,我将不得不重复相同的块.它也违反了DRY,因为如果我有两种形式用于同一件事,我必须写相同的,除了:再次.

cet*_*eek 7

有两种选择:

a)使用try块来保存模型并捕获IntegrityError并处理它.就像是:

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"]
Run Code Online (Sandbox Code Playgroud)

b)在表单的clean()方法中,检查是否存在一行并forms.ValidationError使用适当的消息引发一行 .这里的例子.


所以,b)它是......这就是我引用文档的原因; 所有你需要的就是那里.

但它会是这样的:

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
Run Code Online (Sandbox Code Playgroud)

对于它的价值 - 我刚刚意识到你的unique_together正在引用一个名为username的字段,该字段未在模型中表示.

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