Adding "Previous" and "Next" buttons in Django Admin's Change Form

publié le 14 July 2011

[fr] L'interface d'édition d'un objet de l'admin Django ne prévoit pas de lien vers l'objet précédent ou suivant. Dans cet article, je décris une manière simple d'en ajouter.

In the same application where I used some DB denormalization, I was also asked to add buttons to go directly from a contact's edit page to the edit page for the previous or next contact.

I first thought there would be some magical invocation in the ModelAdmin definition - like

class ContactAdmin(admin.ModelAdmin):
    [...]
    # does not work!!
    previous_next_buttons = True

But this option does not exist. Thinking about it, it does make sense: previous and next are quite contextual notions, so you'll have to implement them yourself.

Fortunately, it happenend to be very easy to do:

  • First, define what you call previous and next, e.g.

    class Contact(models.Model):
    
        [...]
    
        def next(self):
            try:
                return Contact.objects.get(pk=self.pk+1)
            except:
                return None
    
        def previous(self):
            try:
                return Contact.objects.get(pk=self.pk-1)
            except:
                return None
    

    (These definitions are arguably too simplistic... but as I said, this is the context-dependant part, so you'll have to find by yourself what's significant in your case!)

  • Then in your templates directory, add a admin/main/contact/change_form.html (or whatever path you need there) overriding the object-tools block:

    {% block object-tools %}
    <ul class="object-tools">
      {% if change %}{% if not is_popup %}
        <li><a href="history/" class="historylink">{% trans "History" %}</a></li>
        {% if has_absolute_url %}
            <li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">
                {% trans "View on site" %}</a>
            </li>
        {% endif%}
        {% if original.previous %}<li><a href="{% url admin:main_contact_change original.previous.id %}" class="historylink">« {{original.previous}}</a></li>{% endif %}
        {% if original.next %}<li><a href="{% url admin:main_contact_change original.next.id %}" class="historylink">{{original.next}} »</a></li>{% endif %}
      {% endif %}{% endif %}
    </ul>
    {% endblock %}
    

    (This is mostly copy-pasted from the original template file, except for the two last if's)

And voilà! Your change form now has the desired buttons. (As you can see below, I added some other buttons too, but the previous and next are there)

Screenshot of the result

Update June 14th, 2012 Fixed a few errors pointed out by David Feinzeig. Thanks!