3

管理ビューで更新されるインラインフォームに対してclean_field()メソッドが呼び出されない理由がわかりません。私が持っているコードは単純なようです(以下の概要を参照)。

http://admin/..../primary/1/予想どおり、管理インターフェイス()を使用してプライマリフォームを変更すると、次のように表示されます。

  • Admin.PrimaryAdminForm.clean_myfield()と呼ばれる
  • Admin.PrimaryAdminForm.clean()と呼ばれる
  • Model.Primary.clean()と呼ばれる

ただし、メンバーシップ(http://admin/..../membership/1/)の管理者ビューでインラインとして表示されるようにプライマリを変更すると、次のように表示されます。

  • Model.Primary.clean()と呼ばれる

「defclean_myfield(self):」メ​​ソッドを次の場所に配置しようとしましたが、メンバーシップのインライン化されたプライマリフォームから実行されることを確認できません。

  • Model.Primary.clean_myfield
  • Admin.PrimaryAdmin.clean_myfield
  • Admin.PrimaryAdminForm.clean_myfield
  • Admin.PrimaryAdminInline.clean_myfield

このclean_myfieldコードを他の場所に配置する必要がありますか?

[フォームとフィールドの検証][docs.djangoproject.com/en/dev/ref/forms/validation/#form-and-field-validation]に関するDjangoのドキュメントを読みました(そして読み直しました)。インライン検証には何もありません。docs.djangoproject.com/en/dev/ref/contrib/admin/#adding-custom-validation-to-the-adminも読みましたが、インライン固有の検証のヘルプはありません。これに関する他のドキュメントはありますか?

---> Austinによる回答は、「指定されていない場合」(彼のリンクを参照)へのドキュメント参照を提供しました。これは、回答を意味します。このトピックに関するドキュメントを改善するためのリクエストを追加しました。

さらに実験した後、Model.Primary.clean()メソッドにコードを配置することで回避策を見つけました。

def clean(self):
    data = self.myfield
    data += "_extra" # not actual cleaning code 
    self.myfield = data

したがって、疑問が残ります。なぜModel.clean()が、clean_myfield(self)メソッドではなく、adminインラインフォーム検証を配置する唯一の場所であるように見えるのですか?

--->オースティンが回答しましたform = PrimaryAdminFormPrimaryInlineに追加する必要がありました。この追加により、PrimaryInline myfieldがメンバーシップフォームで更新されたときに、PrimaryAdminForm.clean_myfield(self)が呼び出されます。フォーム参照が追加されたため、コードの順序が更新されました。

コードの概要:

forms.pyファイルはありません -すべてのモデルは管理インターフェースを介して更新されます

models.py:

class Membership(models.Model):
    name = models.CharField( max_length=NAME_LENGTH,
        null=True, blank=True, verbose_name="Membership Name Tag",
        help_text="Name of membership" )

class Primary(models.Model):
    user = models.OneToOneField(User, verbose_name="User Name")
    membership = models.OneToOneField(Membership, verbose_name="Membership Name")
    myfield = models.CharField("My Field", max_length=20, null=True, blank=True)


    # clean method altered as in Update comment 
    # Why must this be here? Why not in clean_myfield(self)
    def clean(self):
        data = self.myfield
        data += "_extra" # not actual cleaning code 
        self.myfield = data

admin.py:

class MembershipAdminForm(ModelForm):
    class Meta:
        model = Membership

class PrimaryAdminForm(ModelForm):
    class Meta:
        model = Primary

    def clean_myfield(self):
        data = self.cleaned_data['myfield']
        data += "_extra" # not actual cleaning code 
        return unicode(data)

    def clean(self):
        cleaned_data = super(PrimaryAdminForm, self).clean()
        # not actual cleaning code 
        return cleaned_data

# EDIT2: Moved PrimaryInline so it's defined after PrimaryAdminForm 
class PrimaryInline(admin.StackedInline):
    model = Primary
    form = PrimaryAdminForm   #EDIT2 as recommended by Austin
    raw_id_fields = ['user']
    verbose_name_plural = 'Primary Member'
    fieldsets = ((None, {'classes': ('mbship', ),
                         'fields': ('user', 'myfield')}), )

class MembershipAdmin(admin.ModelAdmin):
    form = MembershipAdminForm

    # inlines
    inlines = [PrimaryInline, ]

    fieldsets = ((None, {'classes': ('mbship',),
                         'fields': ('name'), }), )

class PrimaryAdmin(admin.ModelAdmin):
    form = PrimaryAdminForm
    list_display = ('__unicode__', 'user', 'status', 'date_used' )
    search_fields = ['user__first_name', 'user__last_name', 'user__email'] 

    fieldsets = ((None, {'classes': ('mbship',), 
                         'fields': ('user', 'membership', 'myfield'), }), )

    def clean_myfield(self):
        data = self.cleaned_data['myfield']
        data += "_extra" # not actual cleaning code 
        return unicode(data)
4

1 に答える 1

10

検証は、ModelFormオブジェクトではなくModelAdminオブジェクトで行われます。クリーンなメソッドをオーバーライドする場合は、ModelForm必要なモデルごとに独自の子孫を作成する必要があります。

あなたの例では、PrimaryInlineクラスはを指定していませんform指定しない場合、使用されるフォームはになりModelFormます。これには、カスタムのクリーンメソッドは含まれていません。

これを試して:

class PrimaryInline(admin.StackedInline):
    # ... existing code ...
    form = PrimaryAdminForm

これPrimaryAdminFormで、関連clean()するメソッドでカスタムが使用されます。

于 2013-03-11T22:52:41.110 に答える