From f4c92e9c650a0cab74dafb0fd81b2977419c09f3 Mon Sep 17 00:00:00 2001 From: Gabriel Augendre Date: Mon, 1 Jun 2020 13:44:54 +0200 Subject: [PATCH] Improve perfs --- manuels/admin.py | 16 +++++++++++++++ manuels/models.py | 50 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/manuels/admin.py b/manuels/admin.py index a339da7..c3051ce 100644 --- a/manuels/admin.py +++ b/manuels/admin.py @@ -1,4 +1,5 @@ from django.contrib import admin, messages +from django.db.models import Prefetch from import_export import resources, fields from import_export.admin import ExportMixin from import_export.widgets import IntegerWidget, DecimalWidget @@ -69,24 +70,33 @@ class LevelAdmin(ExportMixin, admin.ModelAdmin): list_editable = ['order'] list_display_links = ['name'] + def get_queryset(self, request): + return super(LevelAdmin, self).get_queryset(request).prefetch_related( + Prefetch("book_set", to_attr="prefetched_books")) + def non_acquired_book_count(self, obj: Level): return obj.non_acquired_book_count + non_acquired_book_count.short_description = 'Nombre de livres à acheter (hors consommables)' def non_acquired_book_price(self, obj: Level): return f'{obj.non_acquired_book_price:.2f}€' + non_acquired_book_price.short_description = 'Coût des livres à acheter (hors consommables)' def non_acquired_consumable_count(self, obj: Level): return obj.non_acquired_consumable_count + non_acquired_consumable_count.short_description = 'Nombre de consommables à acheter' def non_acquired_consumable_price(self, obj: Level): return f'{obj.non_acquired_consumable_price:.2f}€' + non_acquired_consumable_price.short_description = 'Coût des consommables à acheter' def non_acquired_total_price(self, obj: Level): return f'{obj.non_acquired_total_price:.2f}€' + non_acquired_total_price.short_description = 'Coût total à acheter' @@ -126,6 +136,9 @@ class BookAdmin(ExportMixin, admin.ModelAdmin): ] readonly_fields = ['created_at', 'updated_at'] + def get_queryset(self, request): + return super(BookAdmin, self).get_queryset(request).select_related("editor", "level", "teacher") + def update_with_decitre(self, request, queryset): for book in queryset: try: @@ -171,3 +184,6 @@ class SuppliesRequirementAdmin(ExportMixin, admin.ModelAdmin): list_editable = ['done'] readonly_fields = ['created_at', 'updated_at'] list_filter = ['done', 'teacher', 'level'] + + def get_queryset(self, request): + return super(SuppliesRequirementAdmin, self).get_queryset(request).select_related("level", "teacher") diff --git a/manuels/models.py b/manuels/models.py index 7863d21..c12b5b2 100644 --- a/manuels/models.py +++ b/manuels/models.py @@ -127,34 +127,56 @@ class Level(BaseModel): def __str__(self): return self.name + @property + def non_acquired_consumables(self): + if hasattr(self, "prefetched_books"): + return filter(lambda book: book.consumable and not book.previously_acquired, self.prefetched_books) + return self.book_set.filter(consumable=True, previously_acquired=False) + @property def non_acquired_consumable_count(self): - return self.book_set.filter(consumable=True, previously_acquired=False).count() + if hasattr(self, "prefetched_books"): + return len(list(self.non_acquired_consumables)) + return self.non_acquired_consumables.count() @property def non_acquired_consumable_price(self): - price = self.book_set.filter(consumable=True, previously_acquired=False).aggregate(Sum('price')).get('price__sum', 0) - if price is None: - return 0 - return price + if hasattr(self, "prefetched_books"): + return sum(map(lambda book: book.price, self.non_acquired_consumables)) + return self.non_acquired_consumables.aggregate(Sum('price')).get( + 'price__sum', 0) + + @property + def non_acquired_books(self): + if hasattr(self, "prefetched_books"): + return filter(lambda book: not book.consumable and not book.previously_acquired, self.prefetched_books) + return self.book_set.filter(consumable=False, previously_acquired=False) @property def non_acquired_book_count(self): - return self.book_set.filter(consumable=False, previously_acquired=False).count() + if hasattr(self, "prefetched_books"): + return len(list(self.non_acquired_books)) + return self.non_acquired_books.count() @property def non_acquired_book_price(self): - price = self.book_set.filter(consumable=False, previously_acquired=False).aggregate(Sum('price')).get('price__sum', 0) - if price is None: - return 0 - return price + if hasattr(self, "prefetched_books"): + return sum(map(lambda book: book.price, self.non_acquired_books)) + return self.non_acquired_books.aggregate(Sum('price')).get( + 'price__sum', 0) + + @property + def non_acquired_items(self): + if hasattr(self, "prefetched_books"): + return filter(lambda book: not book.previously_acquired, self.prefetched_books) + return self.book_set.filter(previously_acquired=False) @property def non_acquired_total_price(self): - price = self.book_set.filter(previously_acquired=False).aggregate(Sum('price')).get('price__sum', 0) - if price is None: - return 0 - return price + if hasattr(self, "prefetched_books"): + return sum(map(lambda book: book.price, self.non_acquired_items)) + return self.non_acquired_items.aggregate(Sum('price')).get( + 'price__sum', 0) class Editor(BaseModel):