Не тащи бизнес-логику в views и serializers. Выноси её в отдельный service layer.
Пока проект маленький, удобно писать всё прямо во view: получил request, дёрнул ORM, что-то посчитал, сохранил, отправил ответ.
Но как только появляются повторяющиеся сценарии, несколько точек входа, celery-задачи, admin, API и тесты, код начинает расползаться.
Хороший паттерн такой:
• view отвечает только за HTTP,
• serializer за валидацию,
• model за данные,
• а вся бизнес-логика живёт в services.
Пример:
# services/order_service.py
from django.db import transaction
from .models import Order, OrderItem
class OrderService:
@staticmethod
@transaction.atomic
def create_order(*, user, items_data):
order = Order.objects.create(user=user, status="new")
order_items = [
OrderItem(
order=order,
product_id=item["product_id"],
quantity=item["quantity"],
price=item["price"],
)
for item in items_data
]
OrderItem.objects.bulk_create(order_items)
return order
Во view тогда остаётся только это:
def create_order_view(request):
serializer = OrderCreateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
order = OrderService.create_order(
user=request.user,
items_data=serializer.validated_data["items"],
)
return Response({"order_id": order.id})
Что это даёт: код проще тестировать, логика не дублируется, её можно использовать в API, admin и background jobs, и становится меньше шансов сломать что-то при росте проекта.
Django-проект становится серьезнее в тот момент, когда ты перестаёшь писать всё во views.
🐍 Python полезные ресурсы
@pythonl