07 Июл 2023
2 мин
436

Разделение бизнес-логики и работы с данными в Django

Когда начинаешь работать с Django, часто сталкиваешься с проблемой, что большая часть кода оказывается в файле models.py. Это может привести к путанице и затруднить

Содержание

Когда начинаешь работать с Django, часто сталкиваешься с проблемой, что большая часть кода оказывается в файле models.py. Это может привести к путанице и затруднить понимание того, что в коде происходит.

Вот типичная ситуация: изначально модель User выглядит простой и понятной:

class User(db.Models):

    def get_present_name(self):
        return self.name or 'Anonymous'

    def activate(self):
        self.status = 'activated'
        self.save()

Но со временем в ней начинают появляться дополнительные функции, связанные не только с работой с базой данных, но и с другими задачами — например, отправкой писем или взаимодействием с удалёнными API. Модель приобретает вид:

class User(db.Models):

    def get_present_name(self): 
        return remote_api.request_user_name(self.uid) or 'Anonymous' 

    def activate(self):
        self.status = 'activated'
        self.save()
        send_mail('Your account is activated!', '…', [self.email])

В итоге всё смешивается: бизнес-логика приложения, взаимодействие с базой данных, работа с внешними сервисами. Такой подход затрудняет поддержку и развитие проекта.

Что же делать? Решение проблемы — это разделение кода на две части:

  1. Модели базы данных. Здесь описывается, какие данные хранит приложение и как с ними работать.
  2. Бизнес-логика приложения. Здесь описывается, что именно делает приложение и как оно это делает.

Как это можно сделать в Django?

Один из подходов — использование сервисного слоя. Сервисный слой — это место, где располагается основная бизнес-логика приложения. Модели базы данных в этом случае занимаются только хранением данных, а все действия, связанные с обработкой этих данных, перемещаются в сервисный слой.

Если вернуться к примеру с моделью User, то можно выделить два сервиса: один для работы с именем пользователя, другой — для активации аккаунта.

class UserNameService:

    @staticmethod
    def get_present_name(user): 
        return remote_api.request_user_name(user.uid) or 'Anonymous'


class UserActivationService:

    @staticmethod
    def activate(user):
        user.status = 'activated'
        user.save()
        send_mail('Your account is activated!', '…', [user.email])

Такой подход помогает сделать код более чистым и понятным. Каждый сервис отвечает за свою конкретную задачу, и код становится более структурированным и удобным для поддержки.

Содержание

Добавить комментарий

Определи профессию по рисунку