首页 文章

Django - clean_field()没有被调用管理员内联表单的更新

提问于
浏览
3

我无法弄清楚为什么没有为在管理视图上更新的内联表单调用clean_field()方法 . 我的代码似乎很简单(见下面的概要) .

当我通过管理界面( http://admin/..../primary/1/ )修改主表单时,如预期的那样,我看到:

  • Admin.PrimaryAdminForm.clean_myfield()调用

  • Admin.PrimaryAdminForm.clean()调用

  • Model.Primary.clean()调用

但是,当我修改主要内容时,在成员资格的管理员视图( http://admin/..../membership/1/ )中将其视为内联,我只看到:

  • Model.Primary.clean()调用

我尝试在以下位置放置“def clean_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,但对内联特定验证没有帮助 . 还有其他文件吗?

---> Answered by Austin 提供了一个doc参考:"If not specified"(见他的链接),这意味着答案 . 我在这个主题上添加了request to improve文档 .

经过进一步的实验,我通过将代码放入Model.Primary.clean()方法找到了一种解决方法:

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

So the question remains :为什么Model.clean()似乎是唯一放置管理内联表单验证而不是clean_myfield(self)方法的地方?

---> Answered by Austin . 我需要将 form = PrimaryAdminForm 添加到PrimaryInline . 通过此添加,在成员资格表单上更新PrimaryInline myfield时,将调用PrimaryAdminForm.clean_myfield(self) . 由于添加了表单引用,代码排序已更新 .

Code synopsis:

没有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)

1 回答

  • 8

    验证发生在 ModelForm 对象上,而不是 ModelAdmin 对象上 . 如果要覆盖任何干净的方法,则必须为每个所需的模型创建自己的 ModelForm 后代 .

    在您的示例中, PrimaryInline 类未指定 form . If not specified,使用的表单是 ModelForm ,它没有任何自定义清理方法 .

    试试这个:

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

    现在,这将使用您的自定义 PrimaryAdminForm 与相关的 clean() 方法 .

相关问题