Сортировка в списке администратора django по пользовательскому полю в алфавитном порядке

У меня есть простое отношение магазин / продукт, и я хочу сортировать продукты в зависимости от названия магазина в алфавитном порядке.

модели:

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)

и в админке:

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

Я знаю, что не могу использовать order_by в пользовательских полях. Поэтому я подумал, что мне нужно переопределить метод get_queryset, возможно? Я нашел множество примеров аннотации для подсчитанных или вычисленных чисел, но никогда для строк.

Вы можете аннотировать поле с условием в queryset и затем, установить его как ordering в @admin.display декораторе для вашего пользовательского поля.

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

При такой реализации стандартная сортировка интерфейса администратора django будет работать для вашего столбца

enter image description here

Если вам нужна только сортировка по умолчанию, вы можете добавить ее в queryset перед возвратом в get_queryset()

queryset.order_by('_store_name')
Вернуться на верх