Django:通过查询模型表单中的数据库来验证数据(使用自定义清理方法)

Django:通过查询模型表单中的数据库来验证数据(使用自定义清理方法),django,forms,customization,Django,Forms,Customization,我正在尝试创建一个自定义清理方法,如果某个特定数据的值已经存在,并且如果是会引发错误,则在db中查找该方法。 我正在使用从其他类(项目)继承的类(子系统)的模型形式。 当我尝试在表单中添加新系统时,我想检查该系统是否已经存在 我在视图函数中获取项目名称 class SubsytemForm(forms.ModelForm): class Meta: model = Subsystem exclude = ('project_name') d

我正在尝试创建一个自定义清理方法,如果某个特定数据的值已经存在,并且如果是会引发错误,则在db中查找该方法。 我正在使用从其他类(项目)继承的类(子系统)的模型形式。 当我尝试在表单中添加新系统时,我想检查该系统是否已经存在

我在视图函数中获取项目名称

class SubsytemForm(forms.ModelForm):  

    class Meta:
        model = Subsystem
        exclude = ('project_name')

    def clean(self,project_name):

        cleaned_data = super(SubsytemForm, self).clean(self,project_name)
        form_subsystem_name = cleaned_data.get("subsystem_name")

        Subsystem.objects.filter(project__project_name=project_name)
        subsystem_objects=Subsystem.objects.filter(project__project_name=project_name)
        nb_subsystem = subsystem_objects.count()

        for i in range (nb_subsystem):
            if (subsystem_objects[i].subsystem_name==form_subsystem_name):
                msg = u"Subsystem already existing"
                self._errors["subsystem_name"] = self.error_class([msg])

            # These fields are no longer valid. Remove them from the
            # cleaned data.
            del cleaned_data["subsystem_name"]
        return cleaned_data
我的视图功能:

def addform(request,project_name):
    if form.is_valid(): 
        form=form.save(commit=False)
        form.project_id=Project.objects.get(project_name=project_name).id 
        form.clean(form,project_name)
        form.save()
这不管用,我不知道怎么办。 我有一个错误:clean()正好接受2个参数(给定1个)

我的模型:

class Project(models.Model):
project_name = models.CharField("Project name", max_length=20)

Class Subsystem(models.Model):
subsystem_name = models.Charfield("Subsystem name", max_length=20)
projects = models.ForeignKey(Project)

执行form=form.save(commit=False)时,将子系统实例存储在变量表单中,但clean方法是在SubsystemForm中定义的。不是吗

这段代码有很多错误

首先,不应该显式调用
clean
。Django会在您调用
表单时自动为您执行此操作。是否有效()
。因为它是自动完成的,所以不能传递额外的参数。在实例化表单时,需要传入参数,并将其作为实例变量保留,干净的代码可以引用

其次,代码实际上只是验证单个字段。因此,它应该在特定的
clean_字段名
方法中完成-即
clean_子系统名
。这样就避免了处理
\u错误
和删除最后不需要的数据的需要

第三,如果你发现自己得到了一些东西的计数,遍历一个范围,然后使用该索引指向原始列表,那么你就错了。在Python中,您应该始终迭代您感兴趣的实际对象(在本例中是queryset)。但是,在这种情况下,这是无关紧要的,因为您应该直接在数据库中查询实际名称并检查它是否存在,而不是通过迭代检查匹配项

因此,把所有这些放在一起:

class SubsytemForm(forms.ModelForm):  

    class Meta:
        model = Subsystem
        exclude = ('project_name')

    def __init__(self, *args, **kwargs):
        self.project_name = kwargs.pop('project_name', None)
        super(SubsystemForm, self).__init__(*args, **kwargs)

    def clean_subsystem_name(self):
        form_subsystem_name = self.cleaned_data.get("subsystem_name")

        existing = Subsystem.objects.filter(
                       project__project_name=self.project_name,
                       subsytem_name=form_subsystem_name
                   ).exists()

        if existing:
            raise forms.ValidationError(u"Subsystem already existing")

        return form_subsystem_name

某种stacktrace可能有用。此外,我不确定是否可以从已清理的数据数组中删除密钥。可能只是将其设置为null或空字符串?然后,在is_valid方法中,您将项目名称添加到form.clean方法中,但我看不到它在代码中的任何地方被定义?这只是一个错误。我想检查表单中输入的子系统名称是否已被使用,因为它必须是唯一的。我使用is_valid方法(django提供的默认方法)检查数据是否正确是的,我这样做是为了将我的子系统实例映射到项目。但是使用form.clean(form,project_name)您没有调用在SubSystemForm中定义的clean方法。首先,您不应该向clean方法添加第二个参数,因为该方法将由form自动调用。is_valid()。当然,没有设置项目名称。如果要根据在其他字段中设置的值重置字段,可以将clean方法移动到子系统模型。无论如何,将模型字段子系统\u名称设置为唯一不是您要查找的吗?不,因为您可以在项目A和项目B中拥有相同的子系统,但在一个项目中,子系统必须是唯一的。非常感谢。我想我理解我的错误,但它仍然不起作用!!事实上,它并没有得到project_name,它只是将project_name设置为None。有什么想法吗?嗯,你已经把
项目名称
从表格中排除了。但是我不明白
项目名称
子系统名称
之间的关系。哪个是实际的模型字段名?我在问题中添加了模型。我从表单中排除了project_name,因为我不希望用户选择要与子系统映射的项目。我把它映射到我的视图中。我认为最好的方法不是排除project_name,而是用value在我的表单中初始化它(使用queryset填充project_name字段?)。我将此字段设置为隐藏。你认为呢?不,在视野中做这件事是正确的。用
obj=form.save(commit=False)
保存表单,分配
obj.project\u name=project\u name
,然后
obj.save()
。现在我不知道你在问什么。答案中的代码显示了如何检查子系统。