Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django admin: how to sort column by custom method

 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?

like image 689
Dmitry Fedotkin Avatar asked Apr 02 '13 09:04

Dmitry Fedotkin


People also ask

Can we customize Django admin panel?

The Django admin is a powerful built-in tool giving you the ability to create, update, and delete objects in your database using a web interface. You can customize the Django admin to do almost anything you want.

What does admin do in Django?

The Django admin application can use your models to automatically build a site area that you can use to create, view, update, and delete records. This can save you a lot of time during development, making it very easy to test your models and get a feel for whether you have the right data.


1 Answers

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'
like image 102
mfitzp Avatar answered Sep 23 '22 05:09

mfitzp