Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django admin list display optimize queryset

In User model i have a method:

@cached_property
    def income(self):
        return PartnerIncome.objects.all().aggregate(Sum('income'))['income__sum']*self.share_of_profit

PartnerIncome model:

class PartnerIncome(models.Model):
    title = models.CharField(max_length=255)
    income = models.FloatField(default=0)

Now i want to show 'inccome' in list_display=('income', ) at admin panel, but each object make extra query to database. How i can make PartnerIncome.objects.all().aggregate(Sum('income')) as a global variable for admin change list...

like image 804
Arti Avatar asked Mar 09 '15 13:03

Arti


People also ask

How to optimize queries in Django?

How to optimize queries in Django admin? ¶ If you have a lot of calculated fields in your admin, you can be running multiple queries per object leading to your admin can becoming quite slow. To fix this you can override the get_queryset method on model admin to annotate the calculated fields.

What is the default admin site in Django?

A Django administrative site is represented by an instance of django.contrib.admin.sites.AdminSite; by default, an instance of this class is created as django.contrib.admin.site and you can register your models and ModelAdmin instances with it. If you want to customize the default admin site, you can override it.

What is the best way to manage content in Django?

One of the most powerful parts of Django is the automatic admin interface. It reads metadata from your models to provide a quick, model-centric interface where trusted users can manage content on your site. The admin’s recommended use is limited to an organization’s internal management tool.

How do I show all items in a change list Django?

See the default template provided by Django ( admin/filter.html) for a concrete example. Set list_max_show_all to control how many items can appear on a “Show all” admin change list page. The admin will display a “Show all” link on the change list only if the total result count is less than or equal to this setting.


1 Answers

How about just overriding the get_queryset method in your ModelAdmin?

class UserAdmin(admin.ModelAdmin):

    list_display = ('income', ...)

    def income(self, obj):
        return obj.income

    def get_queryset(self, request):
       queryset = super(UserAdmin, self).get_queryset(request)
       # you logic here to `annotate`the queryset with income
       return queryset

Documentation on aggregation:

https://docs.djangoproject.com/en/dev/topics/db/aggregation/

Without me really understanding your models and business logic.. here's a snippet from my own code as an example:

class AuthorAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'books_count',)

    def books_count(self, obj):
        return obj.books_count

    def get_queryset(self, request):
        return super(AuthorAdmin, self).get_queryset(
            request).annotate(books_count=Count('books'))
like image 105
mishbah Avatar answered Sep 28 '22 10:09

mishbah