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(Application Programming Interface)接口,对于大多数人来说可能还比较陌生,但实际上我们每天都在与它打交道.无论是使用手机上的应用程序,还是在网上购物,都少不了A ...
- ATtiny88初体验(六):SPI
ATtiny88初体验(六):SPI SPI介绍 ATtiny88自带SPI模块,可以实现数据的全双工三线同步传输.它支持主从两种模式,可以配置为LSB或者MSB优先传输,有7种可编程速率,支持从空闲 ...
- 升讯威在线客服系统的并发高性能数据处理技术:高性能TCP服务器技术
我在业余时间开发维护了一款免费开源的升讯威在线客服系统,也收获了许多用户.对我来说,只要能获得用户的认可,就是我最大的动力. 最近客服系统成功经受住了客户现场组织的压力测试,获得了客户的认可. 客户组 ...
- TOML格式简介
TOML(Tom's Obvious, Minimal Language)是一种用于配置文件的轻量级文本格式,旨在易于阅读和编写.它的设计目标是简单明了,同时也能表达复杂的数据结构.TOML文件通常用 ...
- GIS中的ROI文件可否由.xml格式转为.roi格式?
本文介绍在ENVI软件中,将用户自行绘制的.xml格式的感兴趣区(ROI)文件转换为.roi格式的方法. 对于ENVI软件,其在早期版本中,默认将用户所绘制的感兴趣区文件保存为.roi格式:而 ...
- dedebiz友情链接样式修改
文件位置 /system/taglib/flink.lib.php 45行位置 根据自己需求修改就行
- Python正则表达式——常用re正则表达式集合
文章目录 一.校验数字的表达式 二.校验字符的表达式 三.特殊需求表达式 一.校验数字的表达式 数字:^[0-9]*$ n位的数字:^\d{n}$ 至少n位的数字:^\d{n,}$ m-n位的数字:^ ...
- Redis面试——Redis面试精华知识
从:Redis 使用场景与介绍 -> 数据结构与简单使用 -> 小功能大用处 -> 持久化.主从同步与缓存设计 -> 知识拓展 ,并且分析典型场景下常见的问题,并结合实战演练, ...
- CCF PTA编程培训师资认证
考试费用: 双会员500元,任意一方单会员750元,报名考试同时成为CCF专业会员850元,非会员1000元. P/T2补考费用:双会员200元,任意一方单会员300元,非会员400元. T1补考费用 ...
- 详解.NET依赖注入中对象的创建与“销毁”
在DI容器中注册类型,DI容器就可以帮我们创建类型的实例:如果注册类型实现了IAsyncDisposable或者IDisposable接口,对象销毁时DI容器还会帮我们调用DisposeAsync或D ...