I would like to create a mixin to extend the ModelAdmin class that adds a description text to the view, overriding the default change_list_template.
[admin_extra.py]
class DescriptionAdminMixin(object)
change_list_template = "description_change_list.html"
...
def changelist_view(self, request, extra_context=None):
extra_context = extra_context or {}
extra_context.update({
'description': self.description,
})
return super(DescriptionAdminMixin, self).changelist_view(request, extra_context=extra_context)
[description_change_list.html]
{% extends "admin/change_list.html" %}
{% block object-tools %}
{% block description %}
{% if description %}{{ description }}{% endif %}
{% endblock description %}
{{ block.super }}
{% endblock %}
This works fine if used on a ModelAdmin, but it fails if used on an already subclassed ModelAdmin that also defines change_list_template, as it gets overwritten.
Ex. adding django-import-export mixin:
class MyModelAdmin(DescriptionAdminMixin, ExportMixin, ModelAdmin):
...
where ExportMixin is defined as:
class ExportMixin(ImportExportMixinBase):
...
change_list_template = 'admin/import_export/change_list_export.html'
...
Is there a preferred way to combine both templates?
The solution I use for now is defining a parent_template in the context, and use that in the template to extend from it
[admin_extra.py]
class DescriptionAdminMixin(object)
change_list_template = "description_change_list.
...
def changelist_view(self, request, extra_context=None):
# Define parent object template, or use the default admin change list template
opts = self.model._meta
app_label = opts.app_label
parent_template_list = super(DescriptionAdminMixin, self).change_list_template or [
'admin/%s/%s/change_list.html' % (app_label, opts.model_name),
'admin/%s/change_list.html' % app_label,
'admin/change_list.html'
]
parent_template = SimpleTemplateResponse(None).resolve_template(parent_template_list)
extra_context = extra_context or {}
extra_context.update({
'description': self.description,
'parent_template': parent_template,
})
return super(DescriptionAdminMixin, self).changelist_view(request, extra_context=extra_context)
[description_change_list.html]
{% extends parent_template %}
{% block object-tools %}
{% block description %}
{% if description %}{{ description }}{% endif %}
{% endblock description %}
{{ block.super }}
{% endblock %}
Is there any better solution? Is there a way for the AdminObject to provide the default template, something like get_change_list_template() to avoid doing the template resolution? Or even better some built-in way of getting the template of the parent class?