Django表单验证取决于表单集中的数据

Django表单验证取决于表单集中的数据,django,validation,django-forms,django-admin,Django,Validation,Django Forms,Django Admin,我有以下代码: from django import forms from django.core.exceptions import ValidationError class MyAdminForm(forms.ModelForm): class Meta: model = MyModel def clean(self): cleaned_data = self.cleaned_data max_num_items = cl

我有以下代码:

from django import forms
from django.core.exceptions import ValidationError

class MyAdminForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def clean(self):
        cleaned_data = self.cleaned_data
        max_num_items = cleaned_data['max_num_items']
        inline_items = cleaned_data.get('inlineitem_set', [])

        if len(inline_items) < 2:
            raise ValidationError('There must be at least 2 valid inline items')

        if max_num_items > len(inline_items):
            raise ValidationError('The maximum number of items must match the number of inline items there are')

        return cleaned_data
来自django导入表单的

从django.core.exceptions导入ValidationError
类MyAdminForm(forms.ModelForm):
类元:
model=MyModel
def清洁(自清洁):
已清理的\u数据=自清理的\u数据
max_num_items=已清理的_数据['max_num_items']
inline\u items=cleanned\u data.get('inlineitem\u set',[])
如果len(内联项)<2:
raise ValidationError('必须至少有2个有效的内联项')
如果最大数量项目>长度(内联项目):
raise ValidationError('最大项数必须与存在的内联项数匹配')
返回已清除的数据
我想我可以从
cleaned_data
(通过使用
cleaned_data['inlineitem_set']
)访问表单集,但事实似乎并非如此

我的问题是:

  • 如何访问表单集
  • 我是否需要使用自定义验证创建自定义表单集才能工作
  • 如果需要这样做,如何在
    clean
    方法中访问表单集的“父”表单

  • 我刚刚为自己的项目解决了这个问题。正如您在第二个问题中所建议的,任何需要访问父表单的内联表单集验证都需要位于
    BaseInlineFormset
    子类的
    clean
    方法中

    令人高兴的是,在调用内联表单集的
    clean
    之前,父表单的实例被创建(或者从数据库中检索,如果您正在修改而不是创建它),并且它在那里作为
    self.instance
    可用

    from django.core.exceptions import ValidationError
    class InlineFormset(forms.models.BaseInlineFormSet):
        def clean(self):
            try:
                forms = [f for f in self.forms
                           if  f.cleaned_data
                           # This next line filters out inline objects that did exist
                           # but will be deleted if we let this form validate --
                           # obviously we don't want to count those if our goal is to
                           # enforce a min or max number of related objects.
                           and not f.cleaned_data.get('DELETE', False)]
                if self.instance.parent_foo == 'bar':
                    if len(forms) == 0:
                        raise ValidationError(""" If the parent object's 'foo' is
                        'bar' then it needs at least one related object! """)
            except AttributeError:
                pass
    
    class InlineAdmin(admin.TabularInline):
        model = ParentModel.inlineobjects.through
        formset = InlineFormset
    
    这里的try-except模式是为了防止出现
    AttributeError
    的极端情况,我自己也没有看到过这种情况,但当我们尝试访问表单(在
    self.forms
    中)的
    cleaned_data
    属性时,这种情况显然会出现,但无法验证。这是我从你那里学到的


    (注意:我的项目仍然在Django 1.3上;没有在1.4中尝试过)

    从Django 1.8开始,管理员调用
    clean()
    方法时,
    InlineFormset
    实例成员仍然填充。非常感谢。我在Django 1.9中做了一些非常类似的事情,它工作得很好。我要添加的一件事是在覆盖的clean函数的顶部添加一个
    super(InlineFormset,self)。clean()
    允许您访问表单集中每个表单上的
    cleaned\u数据。很抱歉,我无法对该问题进行投票,但我无法这样做,因为该问题已得到回答,但答案尚未被接受。