【问题标题】:Django - Add an extra field to an inline form in admin interfaceDjango - 在管理界面中的内联表单中添加一个额外的字段
【发布时间】:2011-11-25 16:23:23
【问题描述】:

假设我在admin.py 中有以下内容:

class ImageInline(admin.TabularInline):
    model = Image

class ObjectAdmin(admin.ModelAdmin):
    inlines = [ ImageInline, ]

如何向ImageInline 添加一个不是Image 模型中的字段的额外字段?

【问题讨论】:

    标签: django django-admin django-forms


    【解决方案1】:

    与使用普通 ModelAdmin 的方式相同。 InlineModelAdmin 可以接受表单属性it's mentioned in the docs。因此,创建一个自定义表单,在您的内联中添加您想要的额外字段:

    class ImageInline(admin.TabularInline):
       model = Image
       form = MyCustomForm
    

    【讨论】:

    • MyCustomForm 是否有可能在不添加 form 属性的情况下显示初始字段?如,我只是追加它而不是重写字段。 super 的性质。
    • 好的,我用ModelFormclass Meta: model = Image得到了这个
    【解决方案2】:

    8 年后,接受的答案将不起作用。

    例如,在Django-2.2.3 中的以下设置中呈现MyInlineForm 中的自定义表单字段:

    class MyInlineAdmin(admin.StackedInline):
        model = MyInlineModel
        form = MyInlineForm
    
    @admin.register(MyModelAdmin)
    class MyModelAdmin(admn.ModelAdmin):
        inlines = (MyInlineAdmin,)
    

    灵感来自@santhoshnsscoe,这可以通过覆盖ModelFormMetaclass.__new__来实现:

    解决方案 1:

    from django.forms.models import ModelFormMetaclass
    
    
    class MyModelFormMetaclass(ModelFormMetaclass):
        def __new__(cls, name, bases, attrs):
            for field in ['test_1', 'test_2', 'test_3']:
                attrs[field] = forms.CharField(max_length=30)
            return super().__new__(cls, name, bases, attrs)
    
    
    class MyInlinelForm(forms.ModelForm, metaclass=MyModelFormMetaclass):
        class Meta:
            model = MyInlineModel
            fields = '__all__'
    

    查看相关代码,ModelFormMetaclass继承自DeclarativeFieldsMetaclass,其中attrs被传递给declared_fields的形式:

    for key, value in list(attrs.items()):
        if isinstance(value, Field):
            current_fields.append((key, value))
            attrs.pop(key)
    attrs['declared_fields'] = OrderedDict(current_fields)
    

    基于此观察,并遵循ModelAdmin.get_formsets_with_inlines 的相关文档 我尝试使用ModelAdmin 的方法来丰富declared_fields,它也有效:

    解决方案 2:

    class MyInlineForm(forms.ModelForm):
        class Meta:
            model = MyInlineModel
            fields = '__all__'
    
    class MyInlineAdmin(admin.StackedInline):
        model = MyInlineModel
        form = MyInlineForm
    
    @admin.register(MyModelAdmin)
    class MyModelAdmin(admn.ModelAdmin):
        inlines = (MyInlineAdmin,)
    
    def get_formsets_with_inlines(self, request, obj=None):
        for inline in self.get_inline_instances(request, obj):
            if isinstance(inline, MyInlineAdmn):
                for field in ['test_1', 'test_2', 'test_3']:
                    inline.form.declared_fields[field] = forms.CharField(max_length=30)
    
            yield inline.get_formset(request, obj), inline
    

    【讨论】:

      【解决方案3】:
      class ReactionInline(admin.StackedInline):
      
          model = Reaction
      
          def formfield_for_dbfield(self, db_field, request, **kwargs):
      
              if db_field.name == "reaction":
      
                  from fb_post.constants.enums import Reactions
                  select_choices = [('None', None)] + Reactions.get_list_of_tuples()
      
                  kwargs['widget'] = forms.Select(choices=select_choices) # the other case for ModelAdmin "kwargs['widget'].choices = select_choices" this would work
      
              return super(ReactionInline, self).formfield_for_dbfield(db_field, request, **kwargs)
      

      用于在管理面板上为应用模型的枚举字段(比如反应)添加下拉菜单功能,用于扩展 StackedInline 或 TabularInline 类的类;这会奏效。 comment

      中还给出了另一种情况的解决方案,扩展 ModelAdmin 的类

      【讨论】:

        猜你喜欢
        • 2019-04-15
        • 1970-01-01
        • 2012-05-04
        • 1970-01-01
        • 2011-05-10
        • 2023-01-13
        • 2023-03-07
        • 2015-11-13
        • 2011-07-04
        相关资源
        最近更新 更多