4

次のコードがあります。

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

cleaned_data(を使用して)からフォームセットにアクセスできると思ってcleaned_data['inlineitem_set']いましたが、そうではないようです。

私の質問は次のとおりです。

  1. フォームセットにアクセスするにはどうすればよいですか?
  2. これを機能させるには、カスタム検証を使用してカスタム フォームセットを作成する必要がありますか?
  3. それを行う必要がある場合、そのcleanメソッドでフォームセットの「親」フォームにアクセスするにはどうすればよいですか?
4

1 に答える 1

6

私は自分のプロジェクトでこれを解決しました。2番目の質問で示唆されているように、親フォームへのアクセスを必要とするインラインフォームセット検証は、サブクラスのcleanメソッドに含まれている必要があるようです。BaseInlineFormset

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、私が自分自身を見たことがないが、検証に失敗しcleaned_dataたフォームの属性(in )にアクセスしようとしたときに発生すると思われるコーナーケースを防ぐためのものです。https://stackoverflow.com/a/877920/492075self.formsからこれについて学びました

(注:私のプロジェクトはまだDjango 1.3にあります。これは、1.4では試していません)

于 2013-01-27T02:51:00.660 に答える