[SOLVED] sorting in django admin list by a custom field alphabetically – Stack Overflow

Issue

This Content is from Stack Overflow. Question asked by xtlc

I have a simple store / product relationship and I want to sort the products depending on the store name alphabetically.

models:

class Store(models.Model):
    name = models.CharField("name", max_length = 128)

class Product(models.Model):
    number = models.PositiveIntegerField()
    name = models.CharField("name", max_length = 128)
    store = models.ForeignKey(Store, on_delete = models.CASCADE)

and in the admin:

class ProductAdmin(admin.ModelAdmin):
    list_display = ["number", "name", "get_store_name",]
    
    def get_store_name(self, obj):
        return f"""{obj.store.name}"""

I know I cannot use order_by on custom fields. So I thought I need to override the get_queryset method probably? I found multiple examples to annotate by counted or calculated numbers, but never for strings.



Solution

You can annotate field with condition to queryset and then, set it as ordering in @admin.display decorator for your custom field.

from django.db.models import Case, F, When


class ProductAdmin(admin.ModelAdmin):
    list_display = ["number", "name", "get_store_name"]

    def get_queryset(self, request):
        queryset = super().get_queryset(request)
        queryset = queryset.annotate(
            _store_name=Case(
                When(store__show_name__isnull=True, then=F('store__name')),
                default=F('store__show_name')),
            ),
        )
        return queryset

    @admin.display(ordering='_store_name')
    def get_store_name(self, obj):
        if obj.store.show_name:
            return obj.store.show_name
        return obj.store.name

With this implementation, standard django admin interface sorting will work for your column

enter image description here

If you want just default sorting, you can add it to queryset before return in get_queryset()

queryset.order_by('_store_name')


This Question was asked in StackOverflow by xtlc and Answered by weAreStarsDust It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?