Login

Admin App/Model Custom Ordering

Author:
stephen_mcd
Posted:
February 24, 2010
Language:
Python
Version:
1.1
Score:
2 (after 2 ratings)

This combination of settings.py admin_reorder_tag.py and admin/base_site.html gives you the ability to define custom ordering for the apps and models in the admin app.

  1. Add the setting ADMIN_REORDER to your settings.py as a tuple with each item containing a tuple of the app name and a tuple of the models within it, all defining the ordering to apply.

  2. Drop the template tag code into admin_reorder_tag.py and put this into a templatetag package in one of your installed apps.

  3. Drop the template code into your templates directory as admin/base_site.html

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
"""
A set of tools giving you the ability to define custom ordering for the apps 
and models in the admin app.

1. Add the setting ADMIN_REORDER to your settings.py as a tuple with each item 
   containing a tuple of the app name and a tuple of the models within it, all 
   defining the ordering to apply.
2. Drop the template tag code into admin_reorder_tag.py and put this into a 
   templatetag package in one of your installed apps.
3. Drop the template code into your templates directory as admin/base_site.html

Credits:
--------

Stephen McDonald <[email protected]>

License:
--------

Creative Commons Attribution-Share Alike 3.0 License
http://creativecommons.org/licenses/by-sa/3.0/

When attributing this work, you must maintain the Credits
paragraph above.
"""

################################################################################
# In settings.py define the app/model ordering 
################################################################################

ADMIN_REORDER = (
    ("app_name1", ("App1Model1", "App1Model2", "App1Model3")),
    ("app_name2", ("App2Model1", "App2Model2")),
)


################################################################################
# Add as admin_reorder_tag.py in one of your app's templatetag packages
################################################################################

from django import template
from django.conf import settings
from django.utils.datastructures import SortedDict


register = template.Library()


# from http://www.djangosnippets.org/snippets/1937/
def register_render_tag(renderer):
    """
    Decorator that creates a template tag using the given renderer as the 
    render function for the template tag node - the render function takes two 
    arguments - the template context and the tag token
    """
    def tag(parser, token):
        class TagNode(template.Node):
            def render(self, context):
                return renderer(context, token)
        return TagNode()
    for copy_attr in ("__dict__", "__doc__", "__name__"):
        setattr(tag, copy_attr, getattr(renderer, copy_attr))
    return register.tag(tag)

@register_render_tag
def admin_reorder(context, token):
    """
    Called in admin/base_site.html template override and applies custom ordering 
    of apps/models defined by settings.ADMIN_REORDER
    """
    # sort key function - use index of item in order if exists, otherwise item
    sort = lambda order, item: (order.index(item), "") if item in order else (
        len(order), item) 
    if "app_list" in context:
        # sort the app list
        order = SortedDict(settings.ADMIN_REORDER)
        context["app_list"].sort(key=lambda app: sort(order.keys(), 
        	app["app_url"][:-1]))
        for i, app in enumerate(context["app_list"]):
            # sort the model list for each app
            app_name = app["app_url"][:-1]
            if not app_name:
                app_name = context["request"].path.strip("/").split("/")[-1]
            model_order = [m.lower() for m in order.get(app_name, [])]
            context["app_list"][i]["models"].sort(key=lambda model: 
            	sort(model_order, model["admin_url"].strip("/").split("/")[-1]))
    return ""

################################################################################
# Add to your templates directory as: admin/base_site.html
################################################################################

{% extends "admin/base.html" %}
{% load i18n admin_reorder_tag %}

{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}

{% block branding %}
{% admin_reorder %}
<h1 id="site-name">{% trans 'Django administration' %}</h1>
{% endblock %}

{% block nav-global %}{% endblock %}

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 3 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 3 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 10 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 10 months, 4 weeks ago
  5. Help text hyperlinks by sa2812 11 months, 3 weeks ago

Comments

cek (on May 6, 2012):

done some minor modifications to admin_reorder to make it work (django 1.4):

@register_render_tag
def admin_reorder(context, token):
    """
    Called in admin/base_site.html template override and applies custom ordering
    of apps/models defined by settings.ADMIN_REORDER
    """
    # sort key function - use index of item in order if exists, otherwise item
    sort = lambda order, item: (order.index(item), "") if item in order else (
        len(order), item)
    if "app_list" in context:
        # sort the app list
        order = SortedDict(settings.ADMIN_REORDER)
        context["app_list"].sort(key=lambda app: sort(order.keys(),
            app["app_url"].strip("/").split("/")[-1]))
        for i, app in enumerate(context["app_list"]):
            # sort the model list for each app
            app_name = app["app_url"].strip("/").split("/")[-1]
            if not app_name:
                app_name = context["request"].path.strip("/").split("/")[-1]
            model_order = [m.lower() for m in order.get(app_name, [])]
            context["app_list"][i]["models"].sort(key=lambda model:
            sort(model_order, model["admin_url"].strip("/").split("/")[-1]))
    return ""

#

idbill (on July 9, 2012):

Another typo....5th line from the bottom in the 1.4 modification.

change: app_name = context["request"].path.strip("/").split("/")[-1]

to app_name = app["name"].lower()

#

Please login first before commenting.