【问题标题】:How to manipulate form fields in Django dynamically within ModelAdmin?如何在 ModelAdmin 中动态操作 Django 中的表单字段?
【发布时间】:2011-08-30 07:38:36
【问题描述】:

我在模型中有一个“必需”字段(slug),但想将 ModelAdmin 类中的字段更改为可选。如果用户不填写,则由另一个字段(名称)自动填写。

class SomeModel(model.Model):
  name = model.CharField(max_length=255)
  slug = model.SlugField(unique=True, max_length=255)

我尝试了多种方法,例如在 ModelAdmin 中覆盖 get_form() 或使用 ModelForm 类并专门指定表单。

class SomeModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super(self.__class__, self).get_form(request, obj, **kwargs)
        form.slug.required = False
        return form

但是,这两种解决方案都不适合我。除了手动创建表单之外,还有其他更快的解决方案吗?

我有很多这样的表格,手工操作可能很乏味且难以维护。

【问题讨论】:

    标签: python django forms modeladmin


    【解决方案1】:

    我自己在遇到同样的问题时通过 Google 找到了这个页面。以下内容也适用于ModelAdmin

    def get_form(self, *args, **kwargs):
        form = super(SomeModelAdmin, self).get_form(*args, **kwargs)
        form.base_fields['slug'].required = False
        return form
    

    从更新的ModelFormMetaclass 创建的后续表单将不需要slug 字段。

    这在我的情况下效果更好,我只有一个类,我需要取消该字段,并且不需要在保存时进行任何数据转换。如果您有很多类,或者需要进行数据转换,GoogleDroid 的解决方案会更好。

    【讨论】:

      【解决方案2】:

      在您的 get_form 方法中,form.fields['slug'].required 应该可以工作。

      但正确的做法是提供一个自定义的 ModelForm。

      class SomeModelForm(forms.ModelForm):
          slug = forms.CharField(required=False)
      
      class SomeModelAdmin(admin.ModelAdmin):
          form = SomeModelForm
      

      顺便说一句,请不要super(self.__class__, self)。使用 super 时,您应该始终明确命名当前类,否则任何从您的继承并依次调用 super 的子类都会中断。

      编辑 form.fields,而不是forms.fields

      通过说self.__class__,您明确阻止Python 处理继承——因为它总是引用具体类——即继承树的底部。但是,如果您的方法是该树的中间,那么在 super 中引用具体类是错误的 - 因为您希望它从您所在的位置调用下一个级别,而不是从底部向上调用。这就是为什么你应该始终命名你所在的班级 - 在这种情况下,super(SomeModelAdmin, self)

      【讨论】:

      • 我得到了一个AttributeError,使用forms.fields['slug'].required 表示字段无效属性。由于涉及的工作量很大,由于我拥有的模型数量,我试图避免提供自定义表单。另外,我不完全确定为什么 super(self.__class__, self) 如果被子分类会中断? Python不应该能够根据范围进行计算吗?感谢您对此进行调查。
      • 再次感谢!这是我在这里的一个错字,但在我的代码中是正确的,但仍然无法正常工作。我发现从get_form 返回的表单类型是django.forms.models.ModelFormMetaclassdir(form) 也没有显示字段属性。
      【解决方案3】:

      我只是想报告一下,以防其他人发现这很有用。

      我从来没有能够在get_form 方法中做form.fields['slug'].required 并且从来不知道为什么。但是,我通过创建一个继承自 ModelForm 的新表单解决了我的问题。

      在调用父构造函数后,我必须重写 init() 以设置 self.fields['slug'].required = False,然后如果需要通过访问 self.data['slug'] 来重写 clean_slug() 以修改 slug 字段内容。

      希望这对某人有所帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-31
        • 2022-11-02
        • 2010-11-18
        • 2021-12-18
        • 2016-07-17
        • 2014-02-02
        • 2019-11-03
        • 2011-01-31
        相关资源
        最近更新 更多