管理ビューで更新されるインラインフォームに対して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 = PrimaryAdminForm
PrimaryInlineに追加する必要がありました。この追加により、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)