Privacy Policy
Snippets index

  How to extend the Django admin site with custom views

To include custom administration views in a Django site, you can extend the builtin Django admin site itself

file "backend/admin.py"

from django.contrib import admin
from django.conf.urls import patterns
from django.conf.urls import url
from django.urls import path
from django.shortcuts import get_object_or_404
from .admin_views import color_schema_view

class ColorAdmin(admin.ModelAdmin):

    def get_urls(self):
        info = self.model._meta.app_label, self.model._meta.model_name
        urls = super(ColorAdmin, self).get_urls()
        my_urls = patterns('',

            # or:
            # path('<uuid:pk>/schema/', ...

            url(r'^(?P<object_id>.*)/schema/$',
            self.admin_site.admin_view(self.schema), {},
            name="%s_%s_schema" % info),
        )
        return my_urls + urls

    def schema(self, request, object_id):
        color = get_object_or_404(Color, id=int(object_id))
        return color_schema_view(request, self, color)

file "backend/admin_views.py"

from django.shortcuts import render

def color_schema_view(request, model_admin, object):

    ...

    model = model_admin.model
    opts = model._meta
    return render(
        request,
        'admin/backend/color/schema.html', {
            'opts': opts,
            'has_change_permission': model_admin.has_change_permission(request, object),
            'original': object,
            ...
        }
    )

file "backend/templates/admin/backend/color/change_form.html"

{% extends "admin/change_form.html" %}
{% load i18n %}

{% block object-tools-items %}
    {{ block.super }}
    <li>
        <a href="{% url 'admin:backend_color_schema' object_id %}"><i class="icon-tint icon-alpha75"></i>{% trans 'Test schemas' %}</a>
    </li>
{% endblock %}

file "backend/templates/admin/backend/color/schema.html"

{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}

{% block breadcrumbs %}
<ul class="breadcrumb">
    ...
    ...
    <li>
        {% if has_change_permission %}
            <a href="{% url opts|admin_urlname:'changelist' %}">
                {{ opts.verbose_name_plural|capfirst }}
            </a>
        {% else %}
            {{ opts.verbose_name_plural|capfirst }}
        {% endif %}
        <span class="divider">&raquo;</span>
    </li>
    <li>
        {% if has_change_permission %}
            <a href="{% url opts|admin_urlname:'change' original.id %}">
                {{ original }}
            </a>
        {% else %}
            {{ original }}
        {% endif %}
    </li>
</ul>
{% endblock %}


{% block extrahead %}
    {{ block.super }}
    <script type="text/javascript">
        (function($) {
            $(document).ready(function() {
                $("#colors_lut_form select").on('change', function() {
                    $(this).parent().submit();
                });
            });
        })(jQuery);
    </script>
{% endblock %}


{% block content %}
    <div id="content-main" class="inner-two-columns">

        <h1>{{original}} color schemas</h1>
        ...

    </div>
{% endblock content %}

Another more recent example

@admin.register(Pallet)
class PalletAdmin(BaseModelAdmin):
    ...
    def get_urls(self):
        urls = super().get_urls()
        info = self.model._meta.app_label, self.model._meta.model_name
        my_urls = [
            path('<uuid:object_id>/export-resi/', self.export_resi, name='%s_%s_export-resi' % info),
        ]
        return my_urls + urls

    def export_resi(self, request, object_id):
        obj = Pallet.objects.get(id=object_id)
        next = reverse('admin:backend_pallet_change', args=(obj.id, ))
        try:
            TODO: DO WHAT IS REQUIRED ...
            messages.info(request, '...')
        except Exception as e:
            messages.error(request, str(e))
            if settings.DEBUG:
                messages.warning(request,  traceback.format_exc())
        response = HttpResponseRedirect(next)
        return response
{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}


{% block object-tools-items %}
    <li>
        {% url opts|admin_urlname:'export-resi' original.pk|admin_urlquote as tool_url %}
        <a href="{% add_preserved_filters tool_url %}" class="toollink">Esporta Resi</a>
    </li>
    {{ block.super }}
{% endblock object-tools-items %}