Принятый ответ выше работал в старых версиях django, и вот как я это делал.Это теперь сломалось в более поздних версиях django (сейчас я на 1.68, но даже сейчас оно старое).
Причина, по которой он сейчас сломан, заключается в том, что любые поля в наборах полей возвращаются из ModelAdmin.get_fieldsets) в конечном итоге передаются в качестве параметра fields = для modelform_factory (), что приведет к ошибке, поскольку поля в вашем списке не существуют (и не будут существовать, пока не будет создана ваша форма и не будет вызвана ее __ init __).
Чтобы это исправить, мы должны переопределить ModelAdmin.get_form () и предоставить список полей, который не содержит никаких дополнительных полей, которые будут добавлены позже.Поведение get_form по умолчанию заключается в вызове get_fieldsets () для этой информации, и мы должны предотвратить это:
# CHOOSE ONE
# newer versions of django use this
from django.contrib.admin.utils import flatten_fieldsets
# if above does not work, use this
from django.contrib.admin.util import flatten_fieldsets
class MyModelForm(ModelForm):
def __init__(self, *args, **kwargs):
super(MyModelForm, self).__init__(*args, **kwargs)
# add your dynamic fields here..
for fieldname in ('foo', 'bar', 'baz',):
self.fields[fieldname] = form.CharField()
class MyAdmin(ModelAdmin):
form = MyModelForm
fieldsets = [
# here you put the list of fieldsets you want displayed.. only
# including the ones that are not dynamic
]
def get_form(self, request, obj=None, **kwargs):
# By passing 'fields', we prevent ModelAdmin.get_form from
# looking up the fields itself by calling self.get_fieldsets()
# If you do not do this you will get an error from
# modelform_factory complaining about non-existent fields.
# use this line only for django before 1.9 (but after 1.5??)
kwargs['fields'] = flatten_fieldsets(self.declared_fieldsets)
# use this line only for django 1.9 and later
kwargs['fields'] = flatten_fieldsets(self.fieldsets)
return super(MyAdmin, self).get_form(request, obj, **kwargs)
def get_fieldsets(self, request, obj=None):
fieldsets = super(MyAdmin, self).get_fieldsets(request, obj)
newfieldsets = list(fieldsets)
fields = ['foo', 'bar', 'baz']
newfieldsets.append(['Dynamic Fields', { 'fields': fields }])
return newfieldsets