Где в Django следует размещать бизнес-логику

Ответ

В Django придерживаются принципа "Fat Models, Thin Views" (Толстые модели, Тонкие представления). Бизнес-логику следует распределять по нескольким слоям, чтобы избежать ее концентрации во views.

Основные места для размещения бизнес-логики:

  1. Модели (models.py) Для логики, которая неразрывно связана с конкретным объектом модели. Это могут быть вычисляемые свойства или методы, изменяющие состояние объекта.

    # models.py
    class Order(models.Model):
        total = models.DecimalField(max_digits=10, decimal_places=2)
        is_paid = models.BooleanField(default=False)
    
        def mark_as_paid(self):
            """Логика, связанная с одним заказом."""
            if not self.is_paid:
                self.is_paid = True
                self.save()
  2. Менеджеры моделей (models.py) Для логики, которая оперирует набором объектов (QuerySet), а не одним экземпляром. Идеально для создания объектов со сложной логикой или для кастомных запросов.

    # models.py
    class OrderManager(models.Manager):
        def get_paid_orders(self):
            """Логика, работающая с коллекцией заказов."""
            return self.filter(is_paid=True)
    
    class Order(models.Model):
        # ...
        objects = OrderManager()
  3. Сервисный слой (например, services.py) Для сложной бизнес-логики, которая затрагивает несколько моделей, работает с внешними API или выполняет комплексные операции. Это помогает отделить логику от Django ORM.

    # services.py
    from .models import Order, User
    from external_api import payment_gateway
    
    def process_payment(order: Order, user: User):
        """Комплексная логика, затрагивающая несколько моделей и API."""
        if not order.is_paid:
            payment_gateway.charge(user.credit_card, order.total)
            order.mark_as_paid()
            # send_receipt_email(user)
  4. Формы и Сериализаторы (forms.py, serializers.py) Для логики, связанной исключительно с валидацией и очисткой данных, поступающих от пользователя.

Ключевое правило: Views должны оставаться «тонкими». Их задача — обработать HTTP-запрос, вызвать нужную бизнес-логику из моделей или сервисов и вернуть HTTP-ответ.