django从查询集中排除self以进行验证

时间:2013-12-13 10:59:29

标签: django validation django-queryset

我正在使用自己的clean方法来查看其他表是否已经有一个具有相同字符串的字段。 只要我创建一个,这一切都很顺利,但是当我尝试编辑它时,它会找到“本身”并返回错误。 现在我想知道如何在我的干净方法中排除实例本身

def clean_name(self):
    raw_data = self.cleaned_data['name']
    data = raw_data.title()

    if Country.objects.filter(name=data).exists():
        raise forms.ValidationError(("There is already a country with the name: %s") % data)
    if Province.objects.filter(name=data).exists():
        raise forms.ValidationError(("There is already a province with the name: %s") % data)
    if Region.objects.filter(name=data).exists():
        raise forms.ValidationError(("There is already a region with the name: %s") % data) 
    return data

我知道有一个.exclude()但是需要一个变量与它一起传递,不知道我怎么能用我的干净方法得到它

1 个答案:

答案 0 :(得分:9)

假设您的clean_name方法在ModelForm上,您可以在self.instance访问关联的模型实例。其次,判断模型实例是新创建的还是已存在于数据库中的简单方法是检查其主键的值。如果主键为None,则会新创建模型。

因此,您的验证逻辑可能如下所示:

def clean_name(self):
    name = self.cleaned_data['name'].title()
    qs = Country.objects.filter(name=name)
    if self.instance.pk is not None:
        qs = qs.exclude(pk=self.instance.pk)
    if qs.exists():
        raise forms.ValidationError("There is already a country with name: %s" % name)

为了清晰起见,我只显示了一个查询集。我可能会创建一个包含所有三个查询集的元组,并迭代它们。添加exclude子句的代码和对exists()的调用都可以在循环内处理,因此只需要写一次(DRY)。