Django工程的分层结构

传统上我们都知道在Django中的MTV模式,具体内容含义我们再来回顾一下:

M:是Model的简称,它的目标就是通过定义模型来处理和数据库进行交互,有了这一层或者这种类型的对象,我们就可以通过对象来操作数据。

V:是View的简称,它的工作很少,就是接受用户请求换句话说就是通过HTTP请求接受用户的输入;另外把输入信息发送给处理程并获取结果;最后把结果发送给用户,当然最后这一步还可以使用模板来修饰数据。

T:是Template的简称,这里主要是通过标记语言来定义页面,另外还可以嵌入模板语言让引擎来渲染动态数据。

这时候我们看到网上大多数的列子包括有些视频课程里面只讲MVT以及语法和其他功能实现等,但大家有没有想过一个问题,你的业务逻辑放在哪里?课程中的逻辑通常放在了View里面,就像下面:

# urls.py path('hello/', Hello), path('helloworld/', HelloWorld.as_view()) # View from django.views import View # FVB def Hello(request): if request.method == "GET": return HttpResponse("Hello world") # CVB class HelloWorld(View): def get(self, request): pass def post(self, request): pass

无论是FBV还是CBV,当用户请求进来并通过URL路由找到对应的方法或者类,然后对请求进行处理,比如可以直接返回模型数据、验证用户输入或者校验用户名和密码等。在学习阶段或者功能非常简单的时候使用这种写法没问题,但是对于相对大一点的项目来说你很多具体的处理流程开始出现,而这些东西都写到View里显然你自己都看不下去。

FBV全名Function-based views,基于函数的视图;CBV全名Class-based views,基于类的视图

所以View,它就是一个控制器,它不应该包含业务逻辑,事实上它应该是一个很薄的层。

业务逻辑到底放哪里

网上也有很多文章回答了这个问题,提到了Form层,这个其实是用于验证用户输入数据的格式,比如邮件地址是否正确、是否填写了用户名和密码,至于这个用户名或者邮箱到底在数据库中是否真实存在则不是它应该关心的,它只是一个数据格式验证器。所以业务逻辑到底放哪里呢?显然要引入另外一层。

关于这一层的名称有些人叫做UseCase,也有些人叫做Service,至于什么名字无所谓只要是大家一看就明白的名称就好。如果我们使用UseCase这个名字,那么我们的Djaong工程架构就变成了MUVT,如果是Service那么就MSVT。

这一层的目标是什么呢?它专注于具体业务逻辑,也就是不同用例的具体操作,比如用户注册、登陆和注销都一个用例。所有模型都只是工作流程的一部分并且这一层也知道模型有哪些API。这么说有些空洞,我们用一个例子来说明:

场景是用户注册:

信息填写规范且用户不存在则注册成功并发送账户激活邮件

如果用户已存在则程序引发错误,然后传递到上层并进行告知用户名已被占用

Django 2.2.1、Python 3.7

下图是整个工程的结构

Django工程的分层结构

Models层

models.py

from django.db import models from django.utils.translation import gettext as _ # Create your models here. from django.contrib.auth.models import AbstractUser, UserManager, User class UserAccountManager(UserManager): # 管理器 def find_by_username(self, username): queryset = self.get_queryset() return queryset.filter(username=username) class UserAccount(AbstractUser): # 扩展一个字段,家庭住址 home_address = models.CharField(_('home address'), max_length=150, blank=True) # 账户是否被激活,与users表里默认的is_active不是一回事 is_activated = models.BooleanField(_('activatition'), default=False, help_text=_('新账户注册后是否通过邮件验证激活。'),) # 指定该模型的manager类 objects = UserAccountManager()

我们知道Django会为我们自动建立一个叫做auth_user的表,也就是它自己的认证内容,这个user表本身就是一个模型,它就是继承了AbstractUser类,而这个类有继承了AbstractBaseUser,而这个类继承了models.Model,所以我们这里就是一个模型。再说回AbstractUser类,这个类里面定义了一些username、first_name、email、is_active等用户属性相关的字段,如果你觉得不够用还可以自己扩展。

为了让Django使用我们扩展的用户模型,所以需要在settings.py中添加如下内容:

AUTH_USER_MODEL = "users.UserAccount" 工具类

这个文件主要是放一些通用工具,比如发送邮件这种公共会调用的功能,utils.py内容如下:

from django.core.mail import send_mail from django.contrib.sites.shortcuts import get_current_site from django.contrib.auth.tokens import PasswordResetTokenGenerator from django.utils import six from django.template.loader import render_to_string from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode from django.utils.encoding import force_bytes, force_text from mysite import settings class TokenGenerator(PasswordResetTokenGenerator): def __init__(self): super(TokenGenerator, self).__init__() # def _make_hash_value(self, user, timestamp): # return ( # six.text_type(user.pk) + six.text_type(timestamp) + six.text_type(user.is_active) # ) class WelcomeEmail: subject = 'Activate Your Account' @classmethod def send_to(cls, request, user_account): try: current_site = get_current_site(request) account_activation_token = TokenGenerator() message = render_to_string('activate_account.html', { 'username': user_account.username, 'domain': current_site.domain, 'uid': urlsafe_base64_encode(force_bytes(user_account.id)), 'token': account_activation_token.make_token(user_account), }) send_mail( subject=cls.subject, message=message, from_email=settings.EMAIL_HOST_USER, recipient_list=[user_account.email] ) except Exception as err: print(err)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wppysp.html