In our case, we need to dynamically include additional "exclude" fields in
our VersionableAdmin and not override the selections the developer has set
in their subclass. There are two options to accomplished this:
1) Override get_form() which is messy because you can't just call super
here and modify things. This is a lot of code duplication to just get at
the exclude
def get_form(self, request, obj=None, **kwargs):
"""
Returns a Form class for use in the admin add view. This is used by
add_view and change_view.
"""
if 'fields' in kwargs:
fields = kwargs.pop('fields')
else:
fields = flatten_fieldsets(self.get_fieldsets(request, obj))
if self.exclude is None:
exclude = []
else:
exclude = list(self.exclude)
exclude.extend(self.get_readonly_fields(request, obj))
if self.exclude is None and hasattr(self.form, '_meta') and
self.form._meta.exclude:
# Take the custom ModelForm's Meta.exclude into account only if the
# ModelAdmin doesn't define its own.
exclude.extend(self.form._meta.exclude)
# if exclude is an empty list we pass None to be consistent with the
# default on modelform_factory
exclude = exclude or None
defaults = {
"form": self.form,
"fields": fields,
"exclude": exclude,
"formfield_callback": partial(self.formfield_for_dbfield,
request=request),
}
defaults.update(kwargs)
if defaults['fields'] is None and not
modelform_defines_fields(defaults['form']):
defaults['fields'] = forms.ALL_FIELDS
try:
return modelform_factory(self.model, **defaults)
except FieldError as e:
raise FieldError('%s. Check fields/fieldsets/exclude attributes of
class %s.'
% (e, self.__class__.__name__))
2) Build your own descriptor for exclude:
@property
def exclude(self):
"""
Custom descriptor for exclude since there is no get_exclude method to be
overridden
"""
exclude = self.VERSIONED_EXCLUDE
if super(VersionedAdmin, self).exclude is not None:
# Force cast to list as super exclude could return a tuple
exclude = list(super(VersionedAdmin, self).exclude) + exclude
return exclude
But then this trips the _check_exclude check in ModelAdminChecks for not
being a list or tuple. So you have to subclass that:
class VersionedAdminChecks(ModelAdminChecks):
def _check_exclude(self, cls, model):
"""
Required to suppress error about exclude not being a tuple since we are
using @property to dynamically change it
"""
return []
All of this is a lot of effort just to get at dynamic exclude where
get_exclude() fits the current pattern used in the admin in the current
code base.
--
You received this message because you are subscribed to the Google Groups
"Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-developers/350a8a70-aca9-493b-8ebe-225791cd9a70%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.