Оптимизация запросов на странице клиента
- Устранён 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.core.paginator import Paginator
|
||||
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.views.decorators.http import require_http_methods
|
||||
from django.contrib.auth.decorators import login_required
|
||||
@@ -86,9 +87,18 @@ def customer_detail(request, pk):
|
||||
if customer.is_system_customer:
|
||||
return render(request, 'customers/customer_system.html')
|
||||
|
||||
# Рассчитываем общий долг по активным заказам
|
||||
active_orders = customer.orders.exclude(payment_status='paid')
|
||||
total_debt = sum(order.amount_due for order in active_orders)
|
||||
# Рассчитываем общий долг по активным заказам на стороне БД
|
||||
total_debt_result = customer.orders.exclude(payment_status='paid').aggregate(
|
||||
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)
|
||||
from .models import WalletTransaction
|
||||
@@ -96,8 +106,8 @@ def customer_detail(request, pk):
|
||||
customer=customer
|
||||
).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 заказов на страницу
|
||||
page_number = request.GET.get('page')
|
||||
orders_page = paginator.get_page(page_number)
|
||||
@@ -105,7 +115,7 @@ def customer_detail(request, pk):
|
||||
context = {
|
||||
'customer': customer,
|
||||
'total_debt': total_debt,
|
||||
'active_orders_count': active_orders.count(),
|
||||
'active_orders_count': active_orders_count,
|
||||
'wallet_transactions': wallet_transactions,
|
||||
'orders_page': orders_page,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user