Django - 在管理界面中为内联表单添加一个额外的字段

时间:2011-11-25 16:23:23

标签: django django-admin django-forms

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

class ImageInline(admin.TabularInline):
    model = Image

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

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

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:0)

8年后,接受的答案将无效。

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

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的相关文档 我尝试使用declared_fields的方法丰富ModelAdmin,它也有效:

解决方案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

答案 2 :(得分:0)

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)

用于在管理面板上为应用程序模型的枚举字段添加下拉菜单功能(例如,Reaction),用于扩展StackedInline或TabularInline类的类;这会工作。另一种解决方案,扩展ModelAdmin的类的解决方案,也在评论

中给出