最近在改造一下个人的开发风格。特分享一下。

  • 子应用我一般放在apps中,每个不同模块的子应用起不同的名字。startapp后自己移动一下,记得修改一下Appconfig中的name即可。
  • 子应用中创建services.py或者如有需要可以创建services模块再细分。所有业务放到services中编写。
  • views一律改成apis.py,将views中的业务分割services.py中。
  • 序列化器中一般不写业务相关代码。
  • 提供一个ApiResponse做统一返回,自己继承DRF的response改写一下即可。配合自己异常类,以及全局的异常枚举状态信息。
  • 另外也要改写全局异常捕获处理。做异常统一格式输出。

这里举例一个子应用User。

# apps.users.drf.apis.py
from django.contrib.auth import logout
from rest_framework import serializers
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.request import Request
from rest_framework.views import APIView from apps.users.drf.services import (
user_get_login_data,
user_login,
user_mobile_exist,
user_register,
user_username_exist
)
from utils.drf import ApiResponse
from utils.exception.statuscode import GlobalStatusCode # 用户注册API
class RegisterApi(APIView):
permission_classes = (AllowAny,) # 将序列化器单独定义在api内中,尽量减少重用序列化器
class RegisterInputSerializer(serializers.Serializer):
username = serializers.CharField(required=True)
password = serializers.CharField(required=True)
password2 = serializers.CharField(required=True)
mobile = serializers.CharField(required=True)
allow = serializers.CharField(required=True)
sms_code = serializers.CharField(required=True, min_length=6, max_length=6) def post(self, request: Request):
serializer = self.RegisterInputSerializer(data=request.data)
serializer.is_valid(raise_exception=True) # 调用服务层的方法
user = user_register(request, serializer.validated_data) return ApiResponse(GlobalStatusCode.OK if user else GlobalStatusCode.REGISTER_FAILED_ERR) # 用户登录api
class LoginApi(APIView):
permission_classes = (AllowAny,) class UserLoginSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField() def post(self, request: Request):
serializer = self.UserLoginSerializer(data=request.data)
serializer.is_valid(raise_exception=True) user = user_login(request, serializer.validated_data)
data = user_get_login_data(user=user) return ApiResponse(GlobalStatusCode.OK, data=data) # 用户登出api
class LogoutApi(APIView):
permission_classes = (IsAuthenticated,) def post(self, request: Request):
# 这种就没必要再services.py中定义函数来调用业务了,本身就一行简单的业务代码。
logout(request) return ApiResponse(GlobalStatusCode.OK)

服务层services.py

# apps/user/drf/services.py
import re from django.contrib.auth import authenticate, login
from django.db.models import Q
from django_redis import get_redis_connection
from redis import Redis from apps.users.models import User
from utils.exception.drf import BusinessException
from utils.exception.statuscode import GlobalStatusCode
from utils.regexstring import PHONENUM,PASSWORD,USERNAME def user_username_exist(username):
"""判断用户名是否存在"""
return User.objects.filter(username=username, is_superuser=False).count() > 1 def user_mobile_exist(mobile):
"""判断手机号是否存在"""
return User.objects.filter(mobile=mobile, is_superuser=False).count() > 1 def user_register(request, validated_data) -> User:
"""用户注册业务逻辑""" username = validated_data['username']
mobile = validated_data['mobile']
sms_code = validated_data['sms_code'] # 先校验是否勾选协议,因为不勾选全是白瞎,没必要浪费性能区校验这个那个的..
if validated_data['allow'] != '1':
raise BusinessException(GlobalStatusCode.ALLOW_ERR) # 判断两次输入的密码是否一致
if validated_data['password'] != validated_data['password2']:
raise BusinessException(GlobalStatusCode.CPWD_ERR) # 只需要校验密码是否符合规定就可以了,确认密码不要校验规则,只需要和密码判断是否相同。
if re.match(PASSWORD, validated_data['password']) is None:
raise BusinessException(detail='密码格式不符合规定') if re.match(USERNAME, username) is None:
raise BusinessException(GlobalStatusCode.USER_ERR) if re.match(PHONENUM, mobile) is None:
raise BusinessException(GlobalStatusCode.MOBILE_ERR) # 判断用户是否已注册
user_count = User.objects.filter(Q(username=username) | Q(mobile=mobile)).count()
if user_count > 0:
raise BusinessException(detail='用户已经注册') # 校验短信验证码
from django.conf import settings
if settings.DEBUG:
pass
# 测试环境直接跳过校验验证码
print('测试跳过验证码..')
else:
redis_connection: Redis = get_redis_connection()
code_from_redis = redis_connection.get(validated_data['mobile'])
if code_from_redis is None:
raise BusinessException(detail='短信验证码已过期!请重新获取!') if code_from_redis.decode() != sms_code:
raise BusinessException(detail='短信验证码不正确!请重新输入!') user = User.objects.create_user(
username=validated_data['username'],
password=validated_data['password'],
mobile=validated_data['mobile']
) # 登录
login(request, user) return user def user_get_login_data(*, user: User):
return {
"id": user.id,
"mobile": user.mobile,
"username": user.username,
"email": user.email,
"is_superuser": user.is_superuser,
} def user_login(request, validated_data):
username = validated_data['username'] if re.match(PHONENUM, username) is not None:
User.USERNAME_FIELD = "mobile" user = authenticate(**validated_data) if user is None:
raise BusinessException(GlobalStatusCode.PWD_ERR) login(request, user) return user

django+drf开发一些个人的标准化的更多相关文章

  1. django drf 开发 ~ models基础学习

    零 介绍  对于ORM框架,可以简单的认为自定义类U表示数据库的表:根据类创建的对象表示数据库表一 数据表设计  1 类型统计     CharField->(string)->(1 ma ...

  2. django DRF理解

    django restframework(DRF) 最近的开发过程当中,发现restframework的功能很强大,所以尝试解读了一下源码,写篇博客分享给大家,有错误的地方还请各位多多指出 视图部分 ...

  3. Python之路【第二十三篇】:Django 初探--Django的开发服务器及创建数据库(笔记)

    Django 初探--Django的开发服务器及创建数据库(笔记) 1.Django的开发服务器 Django框架中包含一些轻量级的web应用服务器,开发web项目时不需再对其配置服务器,Django ...

  4. Django web 开发指南 no such table:

    在学习django web开发指南时,发布新博客点击save后会有error提示:no such table balabalabala... 百度了一下说重新运行manage.py syncdb 就可 ...

  5. Django 初探--Django的开发服务器及创建数据库(笔记)

    1.Django的开发服务器 Django框架中包含一些轻量级的web应用服务器,开发web项目时不需再对其配置服务器,Django提供的内置服务器可以在代码修改时自动加载,从而实现网站的迅速开发. ...

  6. 解决Django + DRF:403 FORBIDDEN:CSRF令牌丢失或不正确,{"detail":"CSRF Failed: CSRF cookie not set."}

    我有一个Android客户端应用程序尝试使用Django + DRF后端进行身份验证.但是,当我尝试登录时,我收到以下响应: 403: CSRF Failed: CSRF token missing ...

  7. 在 Django/Flask 开发服务器上使用 HTTPS

    使用 Django 或 Flask 这种框架开发 web app 的时候一般都会用内建服务器开发和调试程序,等程序完成后再移交到生产环境部署.问题是这些内建服务器通常都不支持 HTTPS,我们想在开发 ...

  8. Django Web开发学习笔记(1)

    一.Python的标准类型 (1)bool型 >>> bool("") False >>> bool(None) False >>& ...

  9. Atitit 快速开发的推荐技术标准化 规范 大原则

    Atitit 快速开发的推荐技术标准化 规范 大原则 1. 如何评估什么样的技术适合快速开发??1 1.1. (重要)判断语言层次..层次越高开发效率越高  4gl  dsl> 3.5gl &g ...

  10. [置顶] Django 微信开发(一)——环境搭建

    Django 微信开发(一)——环境搭建 随着移动互联网时代的到来,微信——一个改变着我们生活的产品悄悄走近了我们的生活.我们不得不觉得自己很幸运,自己能在这个世界上遇到像QQ.微博.微信这样优秀的产 ...

随机推荐

  1. 在编写API接口的技术文章时应注意的内容

    编写API接口的技术文章时,建议包含以下内容: 1. 简介:介绍API接口的目的和作用,以及所属的项目或服务. 2. 接口描述:详细描述API接口的功能和使用方法,包括输入参数.输出结果和可能的错误码 ...

  2. Longest Divisors Interval

    Smiling & Weeping ----总有一个人, 一直住在心底, 却消失在生活里. Given a positive integer n, find the maximum size ...

  3. Redis漏洞总结--未授权--沙箱绕过--(CNVD-2015-07557)&&(CNVD-2019-21763)&&(CVE-2022-0543)

    Redis未授权--沙箱绕过--(CNVD-2015-07557)&&(CNVD-2019-21763)&&(CVE-2022-0543) 环境复现 采用Vulfocu ...

  4. centos7.6 安装Jenkins

    一.安装java环境 yum install -y java-11-openjdk* 三.将Jenkins存储库添加到yum repos wget -O /etc/yum.repos.d/jenkin ...

  5. pandas处理大数据题目的操作

    1.用法:DataFrame.drop(labels=None, axis=0, index=None, columns=None, inplace=False) 2.参数说明: labels:要删除 ...

  6. .Net7自定义GC垃圾回收器

    1.前言 CLR和GC高度耦合,.Net7里面分离CLR和GC,则比较容易实现这件事情.本篇来看下,自定义一个GC垃圾回收器. 2.概述 这里首先演示下自定义GC垃圾回收后的效果. 1.下载Custo ...

  7. ERROR: <bits/stdc++.h>, 'cstdalign' file not found, running C++17

    Modified 1 year, 1 month ago Viewed 9k times 4 I'm trying to run a piece of code in Visual Studio Co ...

  8. React-Admin后台管理模板|react18+arco+zustand后台解决方案

    基于react18.x+vite4+arco-design自研中后台管理系统解决方案ReactAdmin. react-vite-admin 基于vite4搭建react18.x后台管理项目.使用了r ...

  9. [MAUI]深入了解.NET MAUI Blazor与Vue的混合开发

    @ 目录 Vue在混合开发中的特点 创建MAUI项目 创建Vue应用 使用element-ui组件库 JavaScript和原生代码的交互 传递根组件参数 从设备调用Javascript代码 从Vue ...

  10. IL编制器 --- Fody

    介绍 这个项目的名称"Fody"来源于属于织巢鸟科(Ploceidae)的小鸟(Fody),本身意义为编织. 核心Fody引擎的代码库地址 :https://github.com/ ...