赞
踩
- # 什么样接口要分页----》获取所有
- # 三种分页方式---》继承GenericAPIView,ListModelMixin
- -list方法---》
- from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
-
- # 基本分页:正常的查第几页,每页显示多少条的方式---》常用
- class CommonPageNumberPagination(PageNumberPagination):
- #4 个类属性
- page_size = 2 #每页显示条数
- page_query_param = 'page' # 查询页码参数 ?page=10
- page_size_query_param = 'size' # ?page=3&size=5000
- max_page_size = 5 #可以通过size控制每页显示的条数,但是通过这个参数控制最多显示多少条
-
- # http://127.0.0.1:8000/books/?page=1&size=300000
-
-
-
- # 偏移分页
- class CommonLimitOffsetPagination(LimitOffsetPagination):
- default_limit = 2 # 每页显示多少条
- limit_query_param = 'limit' # 取多少条
- offset_query_param = 'offset' #从第0个位置偏移多少开始取数据
- max_limit = 5 # 最大限制条数
- # offset=6&limit=90000
- # http://127.0.0.1:8000/books/?limit=3&offset=3 # 从第三条开始取3条
-
- # limit_query_description = _('Number of results to return per page.')
-
-
-
- # 游标分页---》针对于大数据量分页效率高---》可控性差--->只能选择上一页和下一页,不能直接跳转到某一个
- class CommonCursorPagination(CursorPagination):
- cursor_query_param = 'cursor' # 查询的名字 等同于 page=xx
- page_size = 3 # 每页显示多少条
- ordering = 'id' # 排序规则,必须是表中有的字段,一般用id
- #http://127.0.0.1:8000/books/?cursor=cD0z
- from rest_framework.generics import GenericAPIView
- from rest_framework.viewsets import GenericViewSet
- from rest_framework.mixins import ListModelMixin
- from .models import Book
- from .serializer import BookSerializer
-
- # 三种分页方式:
- from .page import CommonPageNumberPagination as PageNumberPagination
- from .page import CommonLimitOffsetPagination
- from .page import CommonCursorPagination
- class BookView(GenericAPIView,ListModelMixin):
- class BookView(GenericViewSet, ListModelMixin):
- queryset = Book.objects.all()
- serializer_class = BookSerializer
-
- pagination_class= CommonCursorPagination
- # APIView实现分页
- from rest_framework.views import APIView
- from rest_framework.viewsets import ViewSet
- from rest_framework.response import Response
- class BookView(ViewSet):
- def list(self,request):
- books=Book.objects.all()
- # 分页
- # paginator=PageNumberPagination()
- paginator=CommonLimitOffsetPagination()
- #分页过后的数据
- qs=paginator.paginate_queryset(books,request,self)
- #序列化
- ser=BookSerializer(qs,many=True)
- # 第一种方式:每页总条数,上一页,下一页
- # return Response(ser.data)
- # 第二种:自己凑
- # return Response({
- # 'count':books.count(),
- # 'next': paginator.get_next_link(),
- # 'previous':paginator.get_previous_link(),
- # 'results': ser.data
- # })
- # 第三种;直接使用分页类的方法
- return paginator.get_paginated_response(ser.data)
- # jwt:Json web token
- # cookie,session,token
- -cookie是存放在客户端浏览器的键值对
- -session是存放在服务端的键值对
- 客户端:sessionId:asdfasdf----》放到cookie中
- 服务端:
- asdfasdf:{id:3,name:lqz}
- dddddd:{id:4,name:pyy}
- -token: 字符串:分三段
- -第一段:头--》公司信息,加密方式。。。
- -第二段:荷载--》放用户信息---->{id:3,name:lqz}
- -第三段:签名---》把第一段和第二段通过某种加密方式+秘钥加密得到一个字符串 asdfads
- -把三段使用base64编码后拼到一起 dasfasd.asdfasdasd.asdfads
- -【token 的签发】---》登录成功后,服务端生成
- -把token串给前端---》前端拿着
- -后面前端只要发请求,就携带token串到后端
- -【token的验证】--》拿到第一段和第二段使用同样的加密方式+秘钥再加密---》得到字符串跟第三段比较,如果一样,表示没有被篡改,如果不一样,表明被篡改了,token不能用了
- -如果没有被篡改,取出第二段 当前登录用户的信息 id
-
- #jwt:Json web token---》只针对于web方向的token方式验证
-
- # token典型样子
- eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
-
- # jwt组成
- -1 header---》{'typ': 'JWT','alg': 'HS256'}---》通过bas64编码后----》eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
- -2 payload---》荷载---》真正用户的数据
- {
- "sub": "1234567890", # 过期时间
- "id":3
- "name": "John Doe",
- "admin": true
- }
- -3 signature---》签名
- header (base64后的)
- payload (base64后的)
- secret
-
- # base64的编码和解码
- -base64的长度一定是4的倍数,如果不到用=补齐
-
- import json
- import base64
- # d={'typ': 'JWT','alg': 'HS256'}
- # s=json.dumps(d)
- # print(s)
-
- #把字符串进行b64编码
- # res=base64.b64encode(bytes(s,encoding='utf-8'))
- # print(res)
-
-
- #把b64编码的字符串,解码
- # b=b'eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJIUzI1NiJ9'
- # res=base64.b64decode(b)
- # print(res)
-
-
- # 开发中使用jwt认证的重点
- -签发token---》登录
- -认证token---》认证类
- # https://github.com/jpadilla/django-rest-framework-jwt
- # https://github.com/jazzband/djangorestframework-simplejwt
- # 用法95%相似
-
- #安装
- pip3 install djangorestframework-jwt
-
- # 快速使用---》使用的表是django的auth的user表---》创建一个用户
-
- # 只需要在路由中配置---》auth的user表中有用户
- from rest_framework_jwt.views import obtain_jwt_token
- urlpatterns = [
- path('login/', obtain_jwt_token),
- ]
- # 登录成功返回格式:{code:100,msg:"登录成功",token:asdfasdf,username:lqz}
-
- # 写一个函数,在配置文件配置
- def jwt_response_payload_handler(token, user=None, request=None):
- return {'code': 100, 'msg': '登陆成功', 'token': token, 'username': user.username}
-
- # 配置文件配置
- JWT_AUTH = {
- 'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.utils.jwt_response_payload_handler',
- }
'运行
- # 只需要在视图类中加入一个认证类,一个权限类
- class BookView(ViewSet):
- # 认证类
- authentication_classes = [JSONWebTokenAuthentication,]
- # 权限类
- permission_classes = [IsAuthenticated,]
-
-
- # 需要在请求头中携带token
- -请求头中key:Authorization
- -请求头的value值:jwt 空格 token串
- 自己定义用户表,实现签发Token功能----登录接口
-
- from rest_framework_jwt.settings import api_settings
-
- jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
- jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
- from rest_framework.decorators import action
- class UserView(ViewSet):
- @action(methods=['POST'],detail=False)
- def login(self, request):
- username = request.data.get('username')
- password = request.data.get('password')
- user = UserInfo.objects.filter(username=username, password=password).first()
- if user:
- # 登录成功---》签发token
- payload = jwt_payload_handler(user) # 根据当前登录用户获取荷载
- print(payload)
- token = jwt_encode_handler(payload) # 根据荷载生成token
-
- return Response({'code': 100, 'msg': '登录成功', 'token': token})
- else:
- return Response({'code': 101, 'msg': '用户名或密码错误'})
- from rest_framework_jwt.settings import api_settings
- from rest_framework import exceptions
- from .models import UserInfo
-
- jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
- jwt_get_username_from_payload = api_settings.JWT_PAYLOAD_GET_USERNAME_HANDLER
-
-
- class LoginAuth(BaseAuthentication):
- def authenticate(self, request):
- # 1 取出 token
- jwt_value = request.META.get('HTTP_TOKEN')
- # 2 验证token是否合法
- # try:
- # payload = jwt_decode_handler(jwt_value)
- # except jwt.ExpiredSignature:
- # msg = 'token过期了'
- # raise exceptions.AuthenticationFailed(msg)
- # except jwt.DecodeError:
- # msg = 'token解码错误'
- # raise exceptions.AuthenticationFailed(msg)
- # except jwt.InvalidTokenError:
- # msg = '解析token未知错误'
- # raise exceptions.AuthenticationFailed(msg)
- try:
- payload = jwt_decode_handler(jwt_value)
- except Exception:
- raise exceptions.AuthenticationFailed('token错误')
-
- print(payload) # 荷载---》user_id
- user = UserInfo.objects.filter(pk=payload['user_id']).first()
- return user, jwt_value
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。