Django Admin multiple admin order fields

I made an override of the ChangeList function so the admin_order_field of a ModelAdmin allows more than one field to order the change list when a column header is clicked.

In your admin.py file, you have to create a special class that will inherit the ChangeList model and override the get_ordering function:


from django.contrib.admin.views.main import ChangeList, ORDER_VAR
class SpecialOrderingChangeList(ChangeList):
""" This is the class that will be overriden in order to change the way the admin_order_fields are read """
def get_ordering(self, request, queryset):
""" This is the function that will be overriden so the admin_order_fields can be used as lists of fields instead of just one field """
params = self.params
ordering = list(self.model_admin.get_ordering(request) or self._get_default_ordering())
if ORDER_VAR in params:
ordering = []
order_params = params[ORDER_VAR].split('.')
for p in order_params:
try:
none, pfx, idx = p.rpartition('-')
field_name = self.list_display[int(idx)]
order_field = self.get_ordering_field(field_name)
if not order_field:
continue
# Here's where all the magic is done: the new method can accept either a list of strings (fields) or a simple string (a single field)
if isinstance(order_field, list):
for field in order_field:
ordering.append(pfx + field)
else:
ordering.append(pfx + order_field)
except (IndexError, ValueError):
continue
ordering.extend(queryset.query.order_by)
pk_name = self.lookup_opts.pk.name
if not (set(ordering) & set(['pk', '-pk', pk_name, '-' + pk_name])):
ordering.append('pk')
return ordering

Then, inside your ModelAdmin class for your model, you have to tell it that the get_changelist function has been replaced:

class myModelAdmin(admin.ModelAdmin):
...
def get_changelist(self, request, **kwargs):
return SpecialOrderingChangeList
...
def special_function1(self, obj):
return obj.something
special_function1.short_description = u"Special Function 1 Heading"
special_function1.admin_order_field = "field3" # Only one field, the original way
def special_function2(self, obj):
return obj.something_else
special_function2.short_description = u"Special Function 2 Heading"
special_function2.admin_order_field = ["field3", "field4", "field5"] # A list of ordering fields, the new method
...
list_display = ("special_function1", "special_function2", "field1", "field2", ...)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: