Search code examples
djangodjango-admin

Django-admin display decorator sorting by multiple columns


In my database model, I have last and first name. In the django-admin site, I want to display "Lastname, Firstname" and have this column sortable. For this, I'm using the @admin.display decorator in my admin.ModelAdmin class.

This decorator takes an ordering parameter which can be a string, referencing a model field name to sort by, for example:

    @admin.display(description = "Full name", ordering = "last_name")
    def full_name(self, obj):
        return f"{obj.last_name}, {obj.first_name}"

However, this will only sort by last_name, obviously, and therefore people with the same last name will end up in arbitrary order. I've tried:

@admin.display(description = "Full name", ordering = ["last_name", "first_name"])

Or using a list instead of a tuple, but this fails ("'tuple' object has no attribute 'startswith'").

I searched for this and found my exact question unanswered here: https://forum.djangoproject.com/t/how-to-tell-admin-display-decorator-to-order-the-results-by-two-columns/21418 Also in this post: Django-admin order by multiple fields someone suggests that the intuitive list syntax would work with "ordering", but this does not seem to work inside the decorator.


Solution

  • Unfortunately that indeed does not work, I tried the same some time ago, and found out it was not implemented (that way). But for this specific case, you can just reproduce the behavior with Concat [Django-doc], to concatenate the two fields together and produce a string, so as in the body of the function:

    from django.db.models import Value
    from django.db.models.functions import Concat
    
    
    @admin.display(
        description='Full name',
        ordering=Concat('last_name', Value(','), 'first_name'),
    )
    def full_name(self, obj):
        return f'{obj.last_name}, {obj.first_name}'