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