diff --git a/myproject/products/models/variants.py b/myproject/products/models/variants.py index dfe7dcf..30e1dfa 100644 --- a/myproject/products/models/variants.py +++ b/myproject/products/models/variants.py @@ -32,17 +32,27 @@ class ProductVariantGroup(models.Model): """ Вариант в наличии, если хотя бы один из его товаров в наличии. Товар в наличии, если Product.in_stock = True. + + Оптимизирован для использования с prefetch_related('items__product'). + Вычисляет результат в памяти без доп. запроса БД. """ - return self.items.filter(product__in_stock=True).exists() + for item in self.items.all(): + if item.product.in_stock: + return True + return False @property def price(self): """ Цена варианта определяется по приоритету товаров: - 1. Берётся цена товара с приоритетом 1, если он в наличии - 2. Если нет - цена товара с приоритетом 2 + 1. Берётся финальная цена товара с приоритетом 1, если он в наличии + 2. Если нет - финальная цена товара с приоритетом 2 3. И так далее по приоритетам - 4. Если ни один товар не в наличии - берётся самый дорогой товар из группы + 4. Если ни один товар не в наличии - берётся максимальная цена из группы + + Финальная цена = sale_price (скидка) если задана, иначе price (основная цена). + Оптимизирован для использования с prefetch_related('items__product'). + Вычисляет результат в памяти без доп. запроса БД. Возвращает Decimal (цену) или None если группа пуста. """ @@ -54,13 +64,14 @@ class ProductVariantGroup(models.Model): # Ищем первый товар в наличии for item in items: if item.product.in_stock: - return item.product.sale_price + return item.product.actual_price - # Если ни один товар не в наличии - берем самый дорогой + # Если ни один товар не в наличии - берем максимальную цену max_price = None for item in items: - if max_price is None or item.product.sale_price > max_price: - max_price = item.product.sale_price + item_price = item.product.actual_price + if max_price is None or item_price > max_price: + max_price = item_price return max_price diff --git a/myproject/products/templates/products/variantgroup_detail.html b/myproject/products/templates/products/variantgroup_detail.html index f501e39..7eb6659 100644 --- a/myproject/products/templates/products/variantgroup_detail.html +++ b/myproject/products/templates/products/variantgroup_detail.html @@ -77,7 +77,7 @@ {{ item.priority }} {{ item.product.name }} {{ item.product.sku }} - {{ item.product.sale_price }} руб. + {{ item.product.actual_price }} руб. {% if item.product.in_stock %} Да diff --git a/myproject/products/views/variant_group_views.py b/myproject/products/views/variant_group_views.py index 8256daf..dec86f7 100644 --- a/myproject/products/views/variant_group_views.py +++ b/myproject/products/views/variant_group_views.py @@ -127,8 +127,12 @@ class ProductVariantGroupDetailView(LoginRequiredMixin, DetailView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - # Получаем товары с приоритетами - context['items'] = self.object.items.all().select_related('product').order_by('priority') + # Используем уже загруженные товары из prefetch_related + # без создания нового queryset для оптимизации БД + context['items'] = sorted( + self.object.items.all(), + key=lambda item: (item.priority, item.id) + ) return context @@ -266,7 +270,7 @@ def product_variant_group_item_move(request, item_id, direction): def _get_items_data(variant_group): - """Возвращает данные о товарах для обновления таблицы""" + """Возвращает данные о товарах для обновления таблицы после AJAX операций""" items = variant_group.items.all().select_related('product').order_by('priority') items_data = [] for item in items: @@ -274,7 +278,7 @@ def _get_items_data(variant_group): 'id': item.id, 'product_name': item.product.name, 'product_sku': item.product.sku, - 'product_price': str(item.product.sale_price), + 'product_price': str(item.product.actual_price), 'priority': item.priority, 'can_move_up': item.priority > 1, 'can_move_down': item.priority < items.count()