Разделение проблем / DI в приложениях Django Rest Framework - PullRequest
1 голос
/ 30 марта 2019

Я пытаюсь создать больше разделения проблем с конечными точками в моих приложениях Django, но не знаю, как реализовать сервисный уровень.Я прочитал популярную статью по питону на эту тему, но она не отвечает на вопросы тестирования.

Например, если у меня есть запрос на сохранение пользователя и я хочу отправить электронное письмо после того, как пользователь был сохранен, популярно обрабатывать эту логику, переопределяя сохранение следующим образом:

**models.py**
class User(AbstractBaseUser, PermissionsMixin):

...

def save(self, *args, **kwargs):
        if self._state.adding:
            user.activate_user(user=self)
        super(User, self).save(*args, **kwargs)

**services.py**
from services import iNotificationService
...

def activate_user(user):
    user.active = True
    iNotificationService().send_message(user)

В приведенном выше примере iNotificationService будет интерфейсом, который приложение может выбрать во время выполнения.Если бы этот пользователь был сохранен в производственной среде, приложение предоставило бы класс, подобный следующему

import mandrill

class EmailClient(iNotificationService)

    def send_message(user):

        message = create_message(user)

        mandrill.send_email(message)

, в модуль services.py для отправки электронного письма.Но если бы приложение запускалось в тестовой среде, то при проверке EmailClient тест выполнялся путем отправки экземпляра интерфейса, чтобы электронная почта не отправлялась:

class iNotificationService(object)

    def send_message(user)
        pass

Мне интересно, какЯ предоставляю экземпляр модулю services.py, чтобы activ_user знал, какой тип уведомления отправлять.Моя единственная идея была в том, чтобы передать аргумент методу save, чтобы он знал, какой тип уведомления использовать.Но мне интересно, насколько масштабируемым было бы это решение, учитывая различные места, в которых можно использовать службу.

1 Ответ

0 голосов
/ 31 марта 2019

Если изменение класса поставщика уведомлений зависит только от среды (тестирование / разработка / производство и т. Д.), В которой вы запускаете приложение (как вы уже упоминали), я бы предложил вам предоставить класс уведомлений для вашего приложения через настройки.Я лично использую этот шаблон и видел его во многих проектах и ​​считаю его очень полезным.

Скажем, у вас есть пакет услуг, в котором есть модуль уведомлений, содержащий все классы провайдеров уведомлений.Вот так.

services
    __init__.py
    notifications.py
        iNotificationService
        EmailClient

Добавить путь к классу провайдера уведомлений в settings.py файле.

settings.py

...
# this value can be changed / overridden based on environment.
# pragmatically or statically.
NOTIFICATION_PROVIDER = 'services.notifications.iNotificationService'
...

services / __ init __. py

from django.conf import settings
from django.utils.module_loading import import_string

def get_notification_provider(*args, **kwargs):
    try:
        notification_class = import_string(settings.NOTIFICATION_PROVIDER)
    except ImportError as e:
        raise ImproperlyConfigured('Error loading notification provider: %s' % e)
    return notification_class(*args, **kwargs)

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

...