wordpress线报主题,宁波最专业的seo公司,淘宝推广费用一般多少,网站建设服务中心接口文档 # 后端把接口写好后#xff1a; 登录接口#xff1a;/api/v1/login --- post---name pwd 注册接口 查询所有图书带过滤接口 # 前后端需要做对接#xff0c;对接第一个东西就是这个接口文档#xff0c;前端照着接口文档开发 公司3个人#xff…接口文档 # 后端把接口写好后 登录接口/api/v1/login --- post---name pwd 注册接口 查询所有图书带过滤接口 # 前后端需要做对接对接第一个东西就是这个接口文档前端照着接口文档开发 公司3个人每个人开发了10个接口3个人都要同时写接口文档 # 接口文档的编写形式 1、worldmd编写,大家都可以操作写完放在git公司的文档管理平台上 2、第三方的接口文档平台(收费) https://www.showdoc.com.cn/ 3、公司自己开发接口文档平台 : 就跟第三方很像 4、公司使用开源的接口文档平台搭建 YAPI百度开源的、 https://zhuanlan.zhihu.com/p/366025001 5、项目自动生成接口文档--drf coreapi、swagger # 接口文档的规范 描述、地址、请求方式、编码方式 请求参数--参数解释必传参数类型 请求体--参数解释必传参数类型 返回示例--返回数据字段解释 错误码解释 # 使用coreapi自动生成接口文档 * 安装 pip install coreapi 总路由
from django.contrib import admin
from rest_framework.documentation import include_docs_urls
from django.urls import path,includeurlpatterns [path(admin/, admin.site.urls),path(docs/, include_docs_urls(title站点页面标题)),path(app/,include(app01.urls)),
]app01路由
from rest_framework.routers import SimpleRouter
from . import views
routerSimpleRouter()
router.register(books, views.BookView, books)
router.register(pubilsh,views.PublishView,pulish)
urlpatterns [
]
urlpatterns router.urls 视图类加注释
class BookView(GenericViewSet, ListModelMixin):返回所有图书接口queryset Book.objects.all()serializer_class BookSerializer# throttle_classes [CommonThrottling]# throttle_classes [MyThrottling]
class PublishView(ListModelMixin, RetrieveModelMixin, CreateModelMixin, GenericViewSet):list:返回出版社列表数据retrieve:返回出版社详情数据create:新增出版社queryset Book.objects.all()serializer_class BookSerializer 序列化类
class BookSerializer(serializers.ModelSerializer):class Meta:model Bookfields [id, name, price, publish, authors, publish_detail, author_list]extra_kwargs {name: {help_text:出版社名字,required:False},publish: {write_only: True,help_text:出版社id号},authors: {write_only: True},publish_detail: {read_only: True},author_list: {read_only: True},}配置文件
INSTALLED_APPS [...app01.apps.App01Config,rest_framework,rest_framework_simplejwt,
]REST_FRAMEWORK {DEFAULT_SCHEMA_CLASS: rest_framework.schemas.coreapi.AutoSchema,
} *表模型或序列化类的字段上写 help_text---会显示在接口文档的字段介绍上 *访问地址 http://127.0.0.1:8000/docs/ jwt介绍 # 概念JWT全名Json web token ,常被用于认证它是一个前端登录认证的方案是token 的一种jwt本质就是token # cookiesessiontoken发展史 https://www.cnblogs.com/liuqingzheng/articles/17858187.html # token *不在服务端存储(session在服务端存储 *token 有三段需要有个加密方式和秘钥来签发token和验证token # jwt-token串,构成三段式使用 . 分割base64编码 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
# 第一段头部header -eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9-声明加密算法公司信息...# 第二段荷载payload -eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9-用户id用户信息token过期时间exptoken签发时间iat...# 第三段签名 signature -TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ-通过某种加密方式秘钥把头和荷载加密后得到-使用它做到防篡改防伪造 base64的编码和解码 # base64 是编码解码方式不是加密方式 import json
import base64
user_info{user_id:999,username:lqz}
# 转成字符串使用base64编码
user_info_strjson.dumps(user_info)
print(user_info_str)# 使用base64编码---bytes格式
resbase64.b64encode(user_info_str.encode(utf-8))
print(res) # eyJ1c2VyX2lkIjogOTk5LCAidXNlcm5hbWUiOiAibHF6In0#base64解码
resbase64.b64decode(eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9)
print(res) # base64特点 大小写数字组合有时候结尾会带 base64编码后的字符串一定是4个倍数如果不足用 补齐最多补3个 # base64实际用途 1、用在jwt中 2、前后端交互可能使用base64编码后交互 百度登录密码先加密使用base64编码向后端发送 3、图片使用base64 前后端传递 12306就是 jwt的快速使用 # JWT是前后端登录认证的方式 登录 --签发token(登录接口) 1 用户携带用户名密码到后端 2 校验用户名密码是否正确如果正确 3 签发token按照jwt逻辑生成三段返回给前端认证token---认证类 1 用户访问我们需要登录的接口 2 携带token过来--请求头请求地址... 3 后端验证用户携带的token是否被篡改是否是伪造的如果没问题 4 认证通过继续后续的逻辑 # jwt快速使用: 1、安装, drf中借助于第三方 pip install djangorestframework-simplejwt 2、路由层 from rest_framework.routers import SimpleRouter
from rest_framework_simplejwt.views import token_obtain_pair, token_verify, token_refresh
from . import views
from django.urls import pathrouterSimpleRouter()
router.register(books, views.BookView, books)
router.register(pubilsh,views.PublishView,pulish)
urlpatterns [path(login/, token_obtain_pair), # 登录签发token-r-》只有这个用的多path(verify/, token_verify), # 验证token 是否有效path(refresh/, token_refresh), # token有过期时间过期不能使用在过期之前可以刷新
] 3、配置文件 INSTALLED_APPS [...app01.apps.App01Config,rest_framework,rest_framework_simplejwt,
]import datetime
SIMPLE_JWT {# token有效时长ACCESS_TOKEN_LIFETIME: datetime.timedelta(minutes30),# token刷新后的有效时间REFRESH_TOKEN_LIFETIME: datetime.timedelta(days1),
} 4、迁移表创建超级用户--- createsuperuser 5、测试登录接口验证接口刷新接口 # 双token认证 access真正使用的token refresh用来更新access access过期时间很短过期后需要重新生成access的token保证token的安全 只要没过期之前签发的access [token] 和后来刷新签发的token都能用 双token认证 # 单token 用户登录签发token----有过期时间 3 minute----重新登录 7 天7天都不需要登录---被别人截货到---不安全 # 双token 用户登录签发了两个token目前的verify验证接口只要是它签的token都会认证通过 access过期时间短 3分 refresh过期时间长7天 用户正常用都用access不用refresh * access一旦过期可以通过refresh这个token调用刷新接口再签发一个access * 通过refresh再次签发token这个过程是不需要登录的对用户就无感知 后续再用access这个token发送请求 优点access一旦被别人截取到拿着模拟发送请求只能在有效时间内很快就会失效 # 认证类不能使用refresh的token 人脸识别逻辑 # 人脸识别---登录---登录后还要签发token 登录 1 用户名密码 2 手机号验证码 3 一键登录 4 扫码登录 5 人脸登录 # 登录成功了付款付大额弹出人脸识别做二次认证 登录里的认证类 # 认证类局部配置、全局配置 局部配置必须配合权限类 class BookView(APIView):# 局部加认证类---带来认证信息会校验不带认证信息不管需要配合一个权限类使用authentication_classes [JWTAuthentication] # 认证类permission_classes [IsAuthenticated] # 权限类没登录的用户没权限 # 前端访问格式必须如下放在请求头中 Authorization Bearer access的token 全局使用它写的登录去除了认证 REST_FRAMEWORK {DEFAULT_AUTHENTICATION_CLASSES: [rest_framework_simplejwt.authentication.JWTAuthentication, # 认证类],DEFAULT_PERMISSION_CLASSES: [rest_framework.permissions.IsAuthenticated, # 权限类],} # 验证使用 refresh的token能不能认证通过 定制返回格式 # 1 我们的目标定制返回格式 {code:100,msg:登录成功,username:lqz,access:asdfasdf.asdfasdf.asdfasdfrefresh:asdfas.ere.we} # 2 顺便看了一下荷载内容 access和refresh是有区分的 # 第二段荷载payload
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
用户id用户信息token过期时间exptoken签发时间iat... # 3 步骤 写个序列化类 # 重写validate 返回什么前端看到什么
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):# 往荷载中加东西classmethoddef get_token(cls, user): # user就是登录成功查到的用户token super().get_token(user) # 签发tokentoken[name] user.username # 往荷载中加用户名return tokendef validate(self, attrs): # 全局钩子old_data super().validate(attrs)data {code: 100,msg: 登录成功成功,username: self.user.username,refresh: old_data[refresh],access: old_data[access]}return data 配置文件配置
SIMPLE_JWT {TOKEN_OBTAIN_SERIALIZER: app01.serializer.MyTokenObtainPairSerializer,
} 视图层: # 定制返回格式(单纯做定制)
from rest_framework.response import Response
from rest_framework.views import APIViewclass BookView(APIView):def get(self, request):return Response(好多书啊) 路由层
from rest_framework_simplejwt.views import token_obtain_pair, token_verify, token_refresh
from django.urls import path
urlpatterns [path(login/, token_obtain_pair), # 登录签发token-r-》只有这个用的多path(verify/, token_verify), # 验证token 是否有效path(refresh/, token_refresh), # token有过期时间过期不能使用在过期之前可以刷新
] 多方式登录之面条版 # 用户输入用户名或手机号或邮箱 密码 都能登录签发token username手机号/邮箱/名 passwordxxx # 使用auth的user表 # 新建项目没问题如果是老项目迁移过数据了按照如下操作 1 删库 2 删除项目中app的迁移文件 3 删除源码中 admin和auth中得迁移记录 4 扩写auth的user表 5 重新迁移 # 面条版登录(简单版) moedels.py
from django.db import models
from django.contrib.auth.models import AbstractUserclass User(AbstractUser):mobile models.CharField(max_length24)icon models.ImageField(upload_toicon, defaulticon/default.png) # 迁移表格
python manage.py makemigrations
python manage.pymigrate
# 创建超级用户
python manage.py createsuperuser class UserView(APIView):authentication_classes ()permission_classes ()def post(self, request):# 1 request取出用户名和密码username request.data.get(username)password request.data.get(password)# 2 使用正则判断用用户名是邮箱手机号还是用户名分别去查询当前用户if re.match(r^1[3-9][0-9]{9}$, username):user User.objects.filter(mobileusername).first()elif re.match(r^..$, username):user User.objects.filter(emailusername).first()else:user User.objects.filter(usernameusername).first()if user and user.check_password(password):# 3 校验密码# 4 签发tokenrefresh TokenObtainPairSerializer.get_token(user)# 5 返回给前端return Response({code: 100, msg: 成功, access: str(refresh.access_token), refresh: str(refresh)})else:return Response({code: 101, msg: 用户名或密码错误}) urls.py
path(books/, views.UserView.as_view()) 多方式登录之升级版1 views.py
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView
from .serializer import LoginSerializerclass UserView(GenericAPIView):authentication_classes ()permission_classes ()serializer_class LoginSerializerdef post(self, request):ser self.get_serializer(datarequest.data)if ser.is_valid(): # 会执行字段自己的校验没有执行局部钩子没有执行全局钩子写了校验用户签发token# context 是视图类和序列化列之间沟通的桥梁access ser.context.get(access)refresh ser.context.get(refresh)username ser.context.get(username)return Response({code: 100, msg: 成功, username: username, access: access, refresh: refresh})else:return Response({code: 101, msg: 用户名或密码错误11}) serializers.py
from rest_framework import serializers
from .models import User
import re
from rest_framework.exceptions import ValidationError
from rest_framework_simplejwt.serializers import TokenObtainPairSerializerclass LoginSerializer(serializers.Serializer):username serializers.CharField()password serializers.CharField()def validate(self, attrs): # 写全局钩子# 校验用户签发tokenusername attrs.get(username)password attrs.get(password)# 2 使用正则判断用用户名是邮箱手机号还是用户名分别去查询当前用户if re.match(r^1[3-9][0-9]{9}$, username):user User.objects.filter(mobileusername).first()elif re.match(r^..$, username):user User.objects.filter(emailusername).first()else:user User.objects.filter(usernameusername).first()if user and user.check_password(password):# 3 校验密码# 4 签发tokenrefresh TokenObtainPairSerializer.get_token(user)self.context[access] str(refresh.access_token)self.context[refresh] str(refresh)self.context[username] user.usernamereturn attrselse:raise ValidationError(用户名或密码错误) 多方式登录之升级版2 # 直接在序列化类里输出格式 views.py
class UserView(GenericAPIView):authentication_classes ()permission_classes ()serializer_class LoginSerializerdef post(self, request):ser LoginSerializer(datarequest.data)if ser.is_valid(): # 会执行字段自己的校验没有执行局部钩子没有执行全局钩子写了校验用户签发token# ser.validated_data # 字典校验过后的数据return Response(ser.validated_data )else:return Response({code: 101, msg: 用户名或密码错误11}) serializers.py
class LoginSerializer(serializers.Serializer):username serializers.CharField()password serializers.CharField()def validate(self, attrs): # 写全局钩子 # 校验用户签发tokenusername attrs.get(username)password attrs.get(password)# 2 使用正则判断用用户名是邮箱手机号还是用户名分别去查询当前用户if re.match(r^1[3-9][0-9]{9}$, username):user User.objects.filter(mobileusername).first()elif re.match(r^..$, username):user User.objects.filter(emailusername).first()else:user User.objects.filter(usernameusername).first()if user and user.check_password(password):# 3 校验密码# 4 签发tokenrefresh TokenObtainPairSerializer.get_token(user)data {code: 100,msg: 登录成功成功,username: self.user.username,refresh:str(refresh),access: str(refresh.access_token)}return dataelse:raise ValidationError(用户名或密码错误) 今日思维导图