Django admin: how to sort column by custom method
Asked Answered
M

1

16
 class Item(models.Model):
     name = models.CharField(max_length=100, unique=True)

     def admin_amount(self):
         total = self.warehouse_set.all().aggregate(item=Sum('amount'))
         return total['item']

 class Warehouse(models.Model):
     name = models.CharField(max_length=100, unique=True)
     item = models.ForeignKey('Item', blank=True, null=True)
     amount = models.IntegerField()

Create new field is wrong, but I cant do something like:

 admin_amount.admin_order_field = 'admin_amount'

I found similar question but I encountered a problem with rewriting queryset() method(can't write something like qs.warehouse_set.all().annotate(models.Sum('amount'))). Is there any way to adapt this solution for me or in my case, there is another solution?

Marquise answered 2/4, 2013 at 9:4 Comment(0)
P
23

Using the code in the linked question (and the suggested edit), the bottom should do it for your example. The principle is to use annotate to add additional data from a sub-query to the returned QuerySet. In this case the Sum of the amounts in warehouses.

Next you add a wrapper function amount_in_warehouses to get this value out for each row, and tell the admin to show this for listing list_display = ('amount_in_warehouses',), and sort on it amount_in_warehouses.admin_order_field = 'amount_in_warehouses'.

class ItemAdmin(admin.ModelAdmin):
    list_display = ('amount_in_warehouses',)
    name = models.CharField(max_length=100, unique=True)

    def queryset(self, request):
        qs = super(ItemAdmin, self).queryset(request)
        qs = qs.annotate(models.Sum('warehouse__amount'))
        return qs

    def amount_in_warehouses(self, obj):
        return obj.warehouse__amount__sum
    amount_in_warehouses.admin_order_field = 'amount_in_warehouses'
Percentile answered 10/4, 2013 at 20:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.