[Django]-How to add button next to Add User button in Django Admin Site

43👍

  1. Create a template in you template folder: admin/YOUR_APP/YOUR_MODEL/change_list.html
  2. Put this into that template

    {% extends "admin/change_list.html" %}
    {% block object-tools-items %}
    
        {{ block.super }}
    
        <li>
            <a href="export/" class="grp-state-focus addlink">Export</a>
        </li>
    
    {% endblock %}
    
  3. Create a view function in YOUR_APP/admin.py and secure it with annotation

    from django.contrib.admin.views.decorators import staff_member_required
    
    @staff_member_required
    def export(self, request):
    
        ... do your stuff ...
    
        return HttpResponseRedirect(request.META["HTTP_REFERER"])
    
  4. Add new url into YOUR_APP/admin.py to url config for admin model

    from django.conf.urls import patterns, include, url
    
    class YOUR_MODELAdmin(admin.ModelAdmin):
    
        ... list def stuff ...
    
        def get_urls(self):
            urls = super(MenuOrderAdmin, self).get_urls()
            my_urls = patterns("",
                url(r"^export/$", export)
            )
            return my_urls + urls
    

Enjoy 😉

👤n1_

0👍

The easy and accepted way is to override the template.

If you don’t want to mess with the Django templates, you could add a Media class to your admin and add some javascript to create the button although I think creating elements with javascript is a bit nasty and should be avoided.

-1👍

Though other answers are entirely valid, I think it is important to note that it is absolutely not necessary to add a button to get such behavior. You can use admin actions, as you did for the make_published action.

This as the advantage of not requiring to override any template, and thus prevent from potential troubles when upgrading django version (as admin templates may change, and changes might not be “compatible” with the way you overrode it).

import csv

from django.http import HttpResponse
from django.utils import timezone

def export_as_csv(modeladmin, request, queryset):
    opts = modeladmin.model._meta
    filename = format(timezone.now(), "{app}_{model}-%Y%m%d_%H%M.csv").format(
        app=opts.app_label, model=opts.model_name)

    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)

    writer = csv.writer(response)
    field_names = [f.get_attname() for f in opts.concrete_fields]
    writer.writerow(field_names)
    for obj in queryset.only(*field_names):
        writer.writerow([str(getattr(obj, f)) for f in field_names])

    return response

Admin actions are made for this, adding a custom button is one step closer to “over-customization”, which means it’s probably time to write your own views.

The admin has many hooks for customization, but beware of trying to use those hooks exclusively. If you need to provide a more process-centric interface that abstracts away the implementation details of database tables and fields, then it’s probably time to write your own views.

Quote from the introduction paragraph of Django Admin’s documentation

Leave a comment