首页 > 解决方案 > Django Rest 框架应用程序中的关注点分离/DI

问题描述

我正在尝试在我的 Django 应用程序中创建更多与端点的关注点分离,但不确定如何实现服务层。我已经阅读了一篇关于这个主题的流行 python 文章,但它似乎没有回答测试问题。

例如,如果我有一个保存用户的请求,并且想在保存用户后发送电子邮件,那么通过覆盖保存来处理这个逻辑是很流行的,如下所示:

**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 模块,以便 activate_user 知道要发送哪种类型的通知。我唯一的想法是将一些参数传递给 save 方法,以便它知道要使用哪种类型的通知。但我想知道考虑到人们可能使用服务的不同地方,该解决方案的可扩展性如何。

标签: djangopython-3.xdjango-rest-framework

解决方案


如果通知提供程序类的更改仅取决于您正在运行应用程序的环境(测试/开发/生产等)(正如您所提到的),我建议您通过设置为您的应用程序提供通知类。我个人使用这种模式,并且在很多项目中都看到过,发现它非常有用。

假设您有一个包含所有通知提供程序类的通知模块的服务包。像这样。

services
    __init__.py
    notifications.py
        iNotificationService
        EmailClient

settings.py在文件中添加通知提供程序类路径。

设置.py

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

服务/__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并在您的应用程序中使用它来根据您的设置获取通知类的实例。您可以根据您的需要/环境在设置中插入不同的提供程序。


推荐阅读