Оптимизация запросов на странице клиента
- Устранён N+1 для статусов заказов: добавлен select_related('status')
- Расчёт total_debt перенесён на сторону БД через aggregate с Greatest/Coalesce
- Избежана загрузка всех активных заказов в память для подсчёта долга
- Количество активных заказов теперь считается через count() без загрузки данных
- Ожидаемый эффект: минус 10+ запросов на страницу, быстрее рендер при большом количестве заказов
This commit is contained in:
@@ -2,7 +2,8 @@ from django.shortcuts import render, get_object_or_404, redirect
|
|||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from django.core.exceptions import ValidationError, PermissionDenied
|
from django.core.exceptions import ValidationError, PermissionDenied
|
||||||
from django.db.models import Q
|
from django.db.models import Q, Sum, F, Value, DecimalField
|
||||||
|
from django.db.models.functions import Greatest, Coalesce
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.views.decorators.http import require_http_methods
|
from django.views.decorators.http import require_http_methods
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
@@ -86,9 +87,18 @@ def customer_detail(request, pk):
|
|||||||
if customer.is_system_customer:
|
if customer.is_system_customer:
|
||||||
return render(request, 'customers/customer_system.html')
|
return render(request, 'customers/customer_system.html')
|
||||||
|
|
||||||
# Рассчитываем общий долг по активным заказам
|
# Рассчитываем общий долг по активным заказам на стороне БД
|
||||||
active_orders = customer.orders.exclude(payment_status='paid')
|
total_debt_result = customer.orders.exclude(payment_status='paid').aggregate(
|
||||||
total_debt = sum(order.amount_due for order in active_orders)
|
total_debt=Coalesce(
|
||||||
|
Sum(Greatest(F('total_amount') - F('amount_paid'), Value(0), output_field=DecimalField())),
|
||||||
|
Value(0),
|
||||||
|
output_field=DecimalField()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
total_debt = total_debt_result['total_debt'] or Decimal('0')
|
||||||
|
|
||||||
|
# Количество активных заказов
|
||||||
|
active_orders_count = customer.orders.exclude(payment_status='paid').count()
|
||||||
|
|
||||||
# История транзакций кошелька (последние 20)
|
# История транзакций кошелька (последние 20)
|
||||||
from .models import WalletTransaction
|
from .models import WalletTransaction
|
||||||
@@ -96,8 +106,8 @@ def customer_detail(request, pk):
|
|||||||
customer=customer
|
customer=customer
|
||||||
).select_related('order', 'created_by').order_by('-created_at')[:20]
|
).select_related('order', 'created_by').order_by('-created_at')[:20]
|
||||||
|
|
||||||
# История заказов с пагинацией
|
# История заказов с пагинацией и оптимизацией запросов
|
||||||
orders_list = customer.orders.all().order_by('-created_at')
|
orders_list = customer.orders.select_related('status').order_by('-created_at')
|
||||||
paginator = Paginator(orders_list, 10) # 10 заказов на страницу
|
paginator = Paginator(orders_list, 10) # 10 заказов на страницу
|
||||||
page_number = request.GET.get('page')
|
page_number = request.GET.get('page')
|
||||||
orders_page = paginator.get_page(page_number)
|
orders_page = paginator.get_page(page_number)
|
||||||
@@ -105,7 +115,7 @@ def customer_detail(request, pk):
|
|||||||
context = {
|
context = {
|
||||||
'customer': customer,
|
'customer': customer,
|
||||||
'total_debt': total_debt,
|
'total_debt': total_debt,
|
||||||
'active_orders_count': active_orders.count(),
|
'active_orders_count': active_orders_count,
|
||||||
'wallet_transactions': wallet_transactions,
|
'wallet_transactions': wallet_transactions,
|
||||||
'orders_page': orders_page,
|
'orders_page': orders_page,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user