django+drf开发一些个人的标准化
最近在改造一下个人的开发风格。特分享一下。
- 子应用我一般放在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开发一些个人的标准化的更多相关文章
- django drf 开发 ~ models基础学习
零 介绍 对于ORM框架,可以简单的认为自定义类U表示数据库的表:根据类创建的对象表示数据库表一 数据表设计 1 类型统计 CharField->(string)->(1 ma ...
- django DRF理解
django restframework(DRF) 最近的开发过程当中,发现restframework的功能很强大,所以尝试解读了一下源码,写篇博客分享给大家,有错误的地方还请各位多多指出 视图部分 ...
- Python之路【第二十三篇】:Django 初探--Django的开发服务器及创建数据库(笔记)
Django 初探--Django的开发服务器及创建数据库(笔记) 1.Django的开发服务器 Django框架中包含一些轻量级的web应用服务器,开发web项目时不需再对其配置服务器,Django ...
- Django web 开发指南 no such table:
在学习django web开发指南时,发布新博客点击save后会有error提示:no such table balabalabala... 百度了一下说重新运行manage.py syncdb 就可 ...
- Django 初探--Django的开发服务器及创建数据库(笔记)
1.Django的开发服务器 Django框架中包含一些轻量级的web应用服务器,开发web项目时不需再对其配置服务器,Django提供的内置服务器可以在代码修改时自动加载,从而实现网站的迅速开发. ...
- 解决Django + DRF:403 FORBIDDEN:CSRF令牌丢失或不正确,{"detail":"CSRF Failed: CSRF cookie not set."}
我有一个Android客户端应用程序尝试使用Django + DRF后端进行身份验证.但是,当我尝试登录时,我收到以下响应: 403: CSRF Failed: CSRF token missing ...
- 在 Django/Flask 开发服务器上使用 HTTPS
使用 Django 或 Flask 这种框架开发 web app 的时候一般都会用内建服务器开发和调试程序,等程序完成后再移交到生产环境部署.问题是这些内建服务器通常都不支持 HTTPS,我们想在开发 ...
- Django Web开发学习笔记(1)
一.Python的标准类型 (1)bool型 >>> bool("") False >>> bool(None) False >>& ...
- Atitit 快速开发的推荐技术标准化 规范 大原则
Atitit 快速开发的推荐技术标准化 规范 大原则 1. 如何评估什么样的技术适合快速开发??1 1.1. (重要)判断语言层次..层次越高开发效率越高 4gl dsl> 3.5gl &g ...
- [置顶] Django 微信开发(一)——环境搭建
Django 微信开发(一)——环境搭建 随着移动互联网时代的到来,微信——一个改变着我们生活的产品悄悄走近了我们的生活.我们不得不觉得自己很幸运,自己能在这个世界上遇到像QQ.微博.微信这样优秀的产 ...
随机推荐
- 在编写API接口的技术文章时应注意的内容
编写API接口的技术文章时,建议包含以下内容: 1. 简介:介绍API接口的目的和作用,以及所属的项目或服务. 2. 接口描述:详细描述API接口的功能和使用方法,包括输入参数.输出结果和可能的错误码 ...
- Longest Divisors Interval
Smiling & Weeping ----总有一个人, 一直住在心底, 却消失在生活里. Given a positive integer n, find the maximum size ...
- Redis漏洞总结--未授权--沙箱绕过--(CNVD-2015-07557)&&(CNVD-2019-21763)&&(CVE-2022-0543)
Redis未授权--沙箱绕过--(CNVD-2015-07557)&&(CNVD-2019-21763)&&(CVE-2022-0543) 环境复现 采用Vulfocu ...
- centos7.6 安装Jenkins
一.安装java环境 yum install -y java-11-openjdk* 三.将Jenkins存储库添加到yum repos wget -O /etc/yum.repos.d/jenkin ...
- pandas处理大数据题目的操作
1.用法:DataFrame.drop(labels=None, axis=0, index=None, columns=None, inplace=False) 2.参数说明: labels:要删除 ...
- .Net7自定义GC垃圾回收器
1.前言 CLR和GC高度耦合,.Net7里面分离CLR和GC,则比较容易实现这件事情.本篇来看下,自定义一个GC垃圾回收器. 2.概述 这里首先演示下自定义GC垃圾回收后的效果. 1.下载Custo ...
- 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 ...
- React-Admin后台管理模板|react18+arco+zustand后台解决方案
基于react18.x+vite4+arco-design自研中后台管理系统解决方案ReactAdmin. react-vite-admin 基于vite4搭建react18.x后台管理项目.使用了r ...
- [MAUI]深入了解.NET MAUI Blazor与Vue的混合开发
@ 目录 Vue在混合开发中的特点 创建MAUI项目 创建Vue应用 使用element-ui组件库 JavaScript和原生代码的交互 传递根组件参数 从设备调用Javascript代码 从Vue ...
- IL编制器 --- Fody
介绍 这个项目的名称"Fody"来源于属于织巢鸟科(Ploceidae)的小鸟(Fody),本身意义为编织. 核心Fody引擎的代码库地址 :https://github.com/ ...