How to combine change_list_template in ModelAdmin mixin

126 views
Skip to first unread message

ecas

unread,
Jun 29, 2017, 7:29:37 AM6/29/17
to Django users

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?



Reply all
Reply to author
Forward
0 new messages