验证对象存在2-5个关系?

时间:2015-07-02 19:19:15

标签: django postgresql validation orm foreign-keys

想象一下,我们正在建立一个民意调查网站,就像Django tutorial中的那个。

有两种型号。一个问题,一个选择。每个选项都有一个问题的外键。我们希望确保每个问题至少有两个选择,但不超过5个选择。

在创建问题时,您还可以同时创建选项。因此,两个对象将同时保存。在保存时,如何验证Question对象是否有2-5个与之关系的选项?

由于你不能在未保存的对象上设置关系,我不确定应该如何实现。我想到的第一个解决方案是在问题对象上设置一个pre_save钩子,但正如我刚才说的那样,对象尚未保存,因此选择对象不能与它有关系。
我想到的第二个解决方案是设置post_save挂钩,保存问题,然后保存选项,然后检查问题是否有2-5个选项。这个解决方案看起来非常糟糕,我确信有更好的方法。

你怎么能得到这种功能?
如果它有所不同我在使用PostgreSQL 9.4的Django 1.8上。

1 个答案:

答案 0 :(得分:1)

您可以通过覆盖可以继承的formset上的clean来执行此类验证:

from django.forms.models import BaseInlineFormSet


class RequiredFormSet(BaseInlineFormSet):

    def clean(self):
        for error in self.errors:
            # If any errors exist, return
            if error:
                return

        completed_formsets = 0
        for cleaned_data in self.cleaned_data:
            # only count the form if it's not being deleted
            if cleaned_data and not cleaned_data.get('DELETE', False):
                completed_formsets += 1

        if completed_formsets < 2 or completed_formsets > 5:
            raise forms.ValidationError("You must enter between "
                "2 and 5 {}".format(self.model._meta.verbose_name))

如果您之后需要使用发布数据调用API,则可以覆盖保存,或者在您的项目中执行以下任何操作。

表单的最小/最大数量可能来自设置,或者在实例化formset时传入,而不是在此示例中对其进行硬编码。