04: DjangoRestFramework使用

梦里梦外; 2021-11-23 16:58 379阅读 0赞

Django其他篇

目录:

  • 1.1 DjangoRestFramework基本使用
  • 1.2 drf认证&权限 模块
  • 1.3 djangorestframework 序列化
  • 1.4 djangorestframework 分页

1.1 DjangoRestFramework基本使用 返回顶部

  1、回顾CBV基本使用

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django.contrib import admin
  2. from django.urls import path,re_path,include
  3. urlpatterns = [
  4. path('admin/', admin.site.urls),
  5. re_path(r'users/',include(('users.urls', 'users'), namespace='users'))
  6. ]

urls.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django.contrib import admin
  2. from django.urls import path,re_path,include
  3. urlpatterns = [
  4. path('admin/', admin.site.urls),
  5. re_path(r'users/',include(('users.urls', 'users'), namespace='users'))
  6. ]

users/urls.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. import json
  2. from django.shortcuts import render,HttpResponse
  3. from django.views import View
  4. class HomeView(View):
  5. def dispatch(self, request, *args, **kwargs):
  6. return super(HomeView, self).dispatch(request, *args, **kwargs)
  7. def get(self, request):
  8. return HttpResponse('get')
  9. def post(self, request):
  10. return HttpResponse('post')

users/views.py

  2、安装DjangoRestFramework

  1. pip install djangorestframework==3.9.2
  2. pip install markdown==3.0.1 # Markdown support for the browsable API.
  3. pip install django-filter==2.1.0 # Filtering support

  3、DjangoRestFramework 基本使用

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django.contrib import admin
  2. from django.urls import path,re_path,include
  3. urlpatterns = [
  4. path('admin/', admin.site.urls),
  5. re_path(r'users/',include(('users.urls', 'users'), namespace='users'))
  6. ]

urls.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django.urls import path,re_path,include
  2. from users import views
  3. urlpatterns = [
  4. re_path(r'info', views.UserInfoViewSet.as_view(), name='user'),
  5. ]

users/urls.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. from rest_framework.views import APIView
  2. from django.http import JsonResponse
  3. class UserInfoViewSet(APIView):
  4. def __init__(self):
  5. super(UserInfoViewSet, self).__init__()
  6. def get(self, request, *args, **kwargs):
  7. result = {
  8. 'status': True,
  9. 'data': 'response data'
  10. }
  11. return JsonResponse(result, status=200)
  12. def post(self, request, *args, **kwargs):
  13. result = {
  14. 'status': True,
  15. 'data': 'response data'
  16. }
  17. return JsonResponse(result, status=200)

users/views.py

1.2 drf认证&权限 模块 返回顶部

  1、authentication基本使用

  1. class UserInfoViewSet(APIView):
  2. authentication_classes = [authentication.IsAuthenticated,] # 用户认证模块
  3. permission_classes = (authentication.IsOwnerOrReadOnly,) # 用户授权模块

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django.contrib import admin
  2. from django.urls import path,re_path,include
  3. urlpatterns = [
  4. path('admin/', admin.site.urls),
  5. re_path(r'users/',include(('users.urls', 'users'), namespace='users'))
  6. ]

urls.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from django.urls import path,re_path,include
  4. from users import views
  5. urlpatterns = [
  6. re_path(r'info', views.UserInfoViewSet.as_view(), name='user'),
  7. ]

users/urls.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. from rest_framework.views import APIView
  2. from django.http import JsonResponse
  3. from common.auth import authentication
  4. class UserInfoViewSet(APIView):
  5. authentication_classes = [authentication.IsAuthenticated,]
  6. permission_classes = (authentication.IsOwnerOrReadOnly,)
  7. def __init__(self):
  8. super(UserInfoViewSet, self).__init__()
  9. def get(self, request, *args, **kwargs):
  10. result = {
  11. 'status': True,
  12. 'data': 'response data'
  13. }
  14. return JsonResponse(result, status=200)
  15. def post(self, request, *args, **kwargs):
  16. result = {
  17. 'status': True,
  18. 'data': 'response data'
  19. }
  20. return JsonResponse(result, status=200)

users/views.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from rest_framework import authentication
  4. from rest_framework import exceptions
  5. from rest_framework import permissions
  6. class IsOwnerOrReadOnly(permissions.BasePermission):
  7. def has_permission(self, request, view):
  8. if False: # 这里暂且不进行权限验证
  9. raise exceptions.ParseError('您没有操作的权限')
  10. return True
  11. class IsAuthenticated(authentication.BaseAuthentication):
  12. def authenticate(self, request):
  13. auth = request.META.get('HTTP_AUTHORIZATION', None) # 获取 header中的 Authorization
  14. if auth is None:
  15. raise exceptions.NotAuthenticated()
  16. '''这里应该是验证token是否合法逻辑'''
  17. # token = Token.objects.filter(key=auth)
  18. # try:
  19. # request.user = token[0].user
  20. # except IndexError:
  21. # raise exceptions.NotAuthenticated('Invalid input Authenticated')
  22. return (request, None)
  23. def authenticate_header(self, request):
  24. msg = 'Invalid token.Please get token first'
  25. return exceptions.NotAuthenticated(msg)

common\auth\authentication.py

  2、测试接口

      1080958-20190607135327292-1123245917.png

1.3 djangorestframework 序列化 返回顶部

    1080958-20190608123957991-1767044880.png 1080958-20190608124145607-1381834048.png 1080958-20190608124345627-376045533.png 1080958-20190608124755552-78905349.png

  1、序列化使用举例(serializers.Serializer

  1. '''1、ser = UserInfoSerializer(instance=obj,many=True)'''
  2. # 对查询实例进行序列化 # ser.data 获取序列化后的json格式数据
  3. '''2、定义显示的字段''' name = serializers.CharField() # 显示普通字段
  4. ut = serializers.CharField(source='ut.type_name') # 显示一对多字段
  5. gp = serializers.SerializerMethodField() # 自定义显示(显示多对多)
  6. xxx = serializers.CharField(source='name') # 也可以自定义显示字段名称

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django.contrib import admin
  2. from django.urls import path,re_path,include
  3. urlpatterns = [
  4. path('admin/', admin.site.urls),
  5. re_path(r'users/',include(('users.urls', 'users'), namespace='users'))
  6. ]

urls.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. '''users/urls.py'''
  2. from django.urls import path,re_path
  3. from users import views
  4. urlpatterns = [
  5. re_path(r'^info/$', views.UserInfoViewSet.as_view(), name='userinfo'),
  6. ]

users/urls.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. '''users/models.py'''
  2. from __future__ import unicode_literals
  3. from django.db import models
  4. class UserInfo(models.Model):
  5. name = models.CharField(max_length=64,unique=True)
  6. ut = models.ForeignKey(to='UserType', on_delete=models.CASCADE)
  7. gp = models.ManyToManyField(to='UserGroup')
  8. class UserType(models.Model):
  9. type_name = models.CharField(max_length=64,unique=True)
  10. class UserGroup(models.Model):
  11. group = models.CharField(max_length=64)

users/models.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. ''' users/views.py'''
  2. from rest_framework.views import APIView
  3. from rest_framework.views import Response
  4. from users.serializers.userinfo_serializers import UserInfoSerializer
  5. from users.models import UserInfo
  6. class UserInfoViewSet(APIView):
  7. def get(self, request, *args, **kwargs):
  8. obj = UserInfo.objects.all()
  9. ser = UserInfoSerializer(instance=obj,many=True)
  10. # ret = json.dumps(ser.data,ensure_ascii=False)
  11. # return HttpResponse(ret)
  12. return Response(ser.data, status=200)
  13. '''
  14. [{
  15. "name": "zhangsan",
  16. "ut": "学生",
  17. "gp": [{
  18. "id": 1,
  19. "gp": "group01"
  20. }, {
  21. "id": 2,
  22. "gp": "group02"
  23. }],
  24. "xxx": "zhangsan"
  25. }, {
  26. "name": "lisi",
  27. "ut": "学生",
  28. "gp": [{
  29. "id": 1,
  30. "gp": "group01"
  31. }],
  32. "xxx": "lisi"
  33. }]

users/views.py

  1. '''users/serializers/userinfo_serializers.py'''
  2. from rest_framework import serializers
  3. from users.models import UserInfo
  4. class UserInfoSerializer(serializers.Serializer):
  5. name = serializers.CharField() # 显示普通字段
  6. ut = serializers.CharField(source='ut.type_name') # 显示一对多字段
  7. gp = serializers.SerializerMethodField() # 自定义显示(显示多对多)
  8. xxx = serializers.CharField(source='name') # 也可以自定义显示字段名称
  9. class Meta:
  10. model = UserInfo
  11. def get_gp(self,row):
  12. '''row: 传过来的正是 UserInfo表的对象'''
  13. gp_obj_list = row.gp.all() # 获取用户所有组
  14. ret = []
  15. for item in gp_obj_list:
  16. ret.append({
  17. 'id':item.id,'gp':item.group})
  18. return ret

  2、序列化使用举例(serializers.ModelSerializer

      1. ModelSerializer本质是继承了Serielizer类添加了部分功能

      2. 在使用上ModelSerializer可以使用 fields = ‘__all__‘ 定义要显示的字段

ContractedBlock.gif ExpandedBlockStart.gif

  1. '''users/serializers/userinfo_serializers.py'''
  2. from rest_framework import serializers
  3. from users.models import UserInfo
  4. class UserInfoSerializer(serializers.ModelSerializer):
  5. # name = serializers.CharField() # 显示普通字段
  6. ut = serializers.CharField(source='ut.type_name') # 显示一对多字段
  7. gp = serializers.SerializerMethodField() # 自定义显示(显示多对多)
  8. xxx = serializers.CharField(source='name') # 也可以自定义显示字段名称
  9. class Meta:
  10. model = UserInfo
  11. # fields = "__all__"
  12. fields = ["name",'ut','gp','xxx'] # 定义显示那些字段
  13. def get_gp(self,row):
  14. '''row: 传过来的正是 UserInfo表的对象'''
  15. gp_obj_list = row.gp.all() # 获取用户所有组
  16. ret = []
  17. for item in gp_obj_list:
  18. ret.append({
  19. 'id':item.id,'gp':item.group})
  20. return ret

serializers.ModelSerializer使用

  3、使用serializers.ModelSerializer 进行数据验证

ContractedBlock.gif ExpandedBlockStart.gif

  1. from rest_framework.views import APIView
  2. from users.serializers.userinfo_serializers import UserInfoSerializer
  3. from users.models import UserInfo
  4. class UserInfoViewSet(APIView):
  5. def get(self, request, *args, **kwargs):
  6. obj = UserInfo.objects.all()
  7. ser = UserInfoSerializer(instance=obj,many=True)
  8. ret = json.dumps(ser.data,ensure_ascii=False)
  9. return HttpResponse(ret)
  10. def post(self, request, *args, **kwargs):
  11. ser = UserInfoSerializer(data=request.data) # 验证,对请求发来的数据进行验证
  12. if ser.is_valid():
  13. print(ser.validated_data) # post请求数据字典
  14. else:
  15. print(ser.errors) # form验证错误信息
  16. return HttpResponse(json.dumps({
  17. 'status':True}))

users/views.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. '''users/serializers/userinfo_serializers.py'''
  2. from rest_framework import serializers
  3. from django.core.exceptions import ValidationError
  4. from users.models import UserInfo
  5. class UserInfoSerializer(serializers.ModelSerializer):
  6. name = serializers.CharField(min_length=10, error_messages={
  7. 'required': '该字段必填'}) # 显示普通字段
  8. ut = serializers.CharField(source='ut.type_name',required=False) # 显示一对多字段
  9. gp = serializers.SerializerMethodField(required=False) # 自定义显示(显示多对多)
  10. xxx = serializers.CharField(source='name', required=False) # 也可以自定义显示字段名称
  11. class Meta:
  12. model = UserInfo
  13. # fields = "__all__"
  14. fields = ["name",'ut','gp','xxx'] # 定义显示那些字段
  15. # 局部钩子:
  16. def validate_name(self, value): # value 是name字段提交的值
  17. if value.startswith('sb'): # 不能以sb开头
  18. raise ValidationError('不能以sb开头')
  19. else:
  20. return value
  21. # 全局钩子找到了
  22. def validate(self, value): # value是所有校验通过数据的字典
  23. name = value.get('name')
  24. if False:
  25. raise ValidationError('全局钩子引发异常')
  26. return value

users/serializers/userinfo_serializers.py

  1. '''1、ser.is_valid()'''
  2. # 验证post请求中数据是否合法
  3. '''2、全局校验钩子'''
  4. def validate(self, value): # value是所有校验通过数据的字典
  5. '''3、局部钩子'''
  6. def validate_name(self, value): # value 是name字段提交的值

1.4 djangorestframework 分页 返回顶部

  1、分页中基本语法

  1. '''1、实例化一个Paginator对象'''
  2. paginator = Paginator(objs, page_size) # paginator对象
  3. '''2、获取总数量&总页数'''
  4. total_count = paginator.count # 总数量
  5. total = paginator.num_pages # 总页数
  6. '''3、使用objs对象获取指定页数内容'''
  7. objs = paginator.page(page)
  8. '''4、对分页后的数据进行序列化操作'''
  9. serializer = Serializer(objs, many=True) # 序列化操作

  2、分页模块使用举例

ContractedBlock.gif ExpandedBlockStart.gif

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. from django.conf import settings
  4. from rest_framework import status
  5. from django.core.paginator import EmptyPage, Paginator, PageNotAnInteger
  6. from rest_framework.views import Response
  7. def Paginators(objs, request, Serializer):
  8. """
  9. objs : 实体对象, queryset
  10. request : 请求对象
  11. Serializer : 对应实体对象的类
  12. page_size : 每页显示多少条数据
  13. page : 显示第几页数据
  14. total_count :总共有多少条数据
  15. total :总页数
  16. """
  17. try:
  18. page_size = int(request.GET.get('page_size', settings.REST_FRAMEWORK['PAGE_SIZE']))
  19. page = int(request.GET.get('page', 1))
  20. except (TypeError, ValueError):
  21. return Response(status=400)
  22. paginator = Paginator(objs, page_size) # paginator对象
  23. total_count = paginator.count
  24. total = paginator.num_pages # 总页数
  25. try:
  26. objs = paginator.page(page)
  27. except PageNotAnInteger:
  28. objs = paginator.page(1)
  29. except EmptyPage:
  30. objs = paginator.page(paginator.num_pages)
  31. serializer = Serializer(objs, many=True) # 序列化操作
  32. return Response(
  33. data={
  34. 'detail': serializer.data,
  35. 'page': page,
  36. 'page_size': page_size,
  37. 'total': total,
  38. 'total_count': total_count
  39. }
  40. )

common/utils/api_paginator.py 自定义分页模块

ContractedBlock.gif ExpandedBlockStart.gif

  1. # 分页
  2. REST_FRAMEWORK = {
  3. # 全局分页
  4. 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
  5. # 关闭api root页面展示
  6. 'DEFAULT_RENDERER_CLASSES': (
  7. 'rest_framework.renderers.JSONRenderer',
  8. ),
  9. 'UNICODE_JSON': False,
  10. # 自定义异常处理
  11. 'EXCEPTION_HANDLER': (
  12. 'common.utils.custom_exception_handler'
  13. ),
  14. 'PAGE_SIZE': 10
  15. }

settings.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. '''users/serializers/userinfo_serializers.py'''
  2. from rest_framework import serializers
  3. from users.models import UserInfo
  4. class UserInfoSerializer(serializers.Serializer):
  5. name = serializers.CharField() # 显示普通字段
  6. ut = serializers.CharField(source='ut.type_name') # 显示一对多字段
  7. gp = serializers.SerializerMethodField() # 自定义显示(显示多对多)
  8. xxx = serializers.CharField(source='name') # 也可以自定义显示字段名称
  9. class Meta:
  10. model = UserInfo
  11. def get_gp(self,row):
  12. '''row: 传过来的正是 UserInfo表的对象'''
  13. gp_obj_list = row.gp.all() # 获取用户所有组
  14. ret = []
  15. for item in gp_obj_list:
  16. ret.append({
  17. 'id':item.id,'gp':item.group})
  18. return ret

users/serializers/userinfo_serializer.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. ''' users/views.py'''
  2. from rest_framework.views import APIView
  3. from rest_framework.views import Response
  4. from users.serializers.userinfo_serializers import UserInfoSerializer
  5. from users.models import UserInfo
  6. from common.utils.api_paginator import Paginators
  7. class UserInfoViewSet(APIView):
  8. queryset = UserInfo.objects.all().order_by('id')
  9. serializer_class = UserInfoSerializer
  10. def get(self, request, *args, **kwargs):
  11. self.queryset = self.queryset.all()
  12. ret = Paginators(self.queryset, request, self.serializer_class)
  13. print(json.dumps(ret.data)) # ret.data 返回的是最终查询的json数据
  14. return Response(ret.data)
  15. # http://127.0.0.1:8000/users/info/?page_size=1
  16. '''
  17. {
  18. "detail": [
  19. {
  20. "name": "zhangsan",
  21. "ut": "学生",
  22. "gp": [
  23. {
  24. "id": 1,
  25. "gp": "group01"
  26. },
  27. {
  28. "id": 2,
  29. "gp": "group02"
  30. }
  31. ],
  32. "xxx": "zhangsan"
  33. }
  34. ],
  35. "page": 1,
  36. "page_size": 1,
  37. "total": 3,
  38. "total_count": 3
  39. }
  40. '''

users/views.py

1.5 JWT:使用djangorestframework-jwt模块进行用户身份验证

   安装: pip install djangorestframework-jwt

   添加应用:python manage.py users

   官方网站:http://getblimp.github.io/django-rest-framework-jwt/#rest-framework-jwt-auth

  1、配置使用JWT

ContractedBlock.gif ExpandedBlockStart.gif

  1. ########### 1、在INSTALLED_APPS中加入'rest_framework.authtoken', #################
  2. INSTALLED_APPS = [
  3. '''
  4. 'rest_framework.authtoken', #
  5. '''
  6. ]
  7. ################### 2、配置jwt验证 ######################
  8. REST_FRAMEWORK = {
  9. # 身份认证
  10. 'DEFAULT_AUTHENTICATION_CLASSES': (
  11. 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
  12. 'rest_framework.authentication.SessionAuthentication',
  13. 'rest_framework.authentication.BasicAuthentication',
  14. ),
  15. }
  16. import datetime
  17. JWT_AUTH = {
  18. 'JWT_AUTH_HEADER_PREFIX': 'JWT',
  19. 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
  20. }
  21. AUTH_USER_MODEL='users.User' # 指定使用users APP中的 model User进行验证

settings.py配置使用JWT

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django.db import models
  2. from django.contrib.auth.models import AbstractUser
  3. class User(AbstractUser):
  4. username = models.CharField(max_length=64, unique=True)
  5. password = models.CharField(max_length=64)
  6. phone = models.CharField(max_length=64)
  7. token = models.CharField(max_length=255)

users/models.py 添加用户认证的User表

ContractedBlock.gif ExpandedBlockStart.gif

  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from rest_framework_jwt.settings import api_settings
  4. from rest_framework import serializers
  5. from users.models import User
  6. class UserSerializer(serializers.Serializer):
  7. username = serializers.CharField()
  8. password = serializers.CharField()
  9. phone = serializers.CharField()
  10. token = serializers.CharField(read_only=True)
  11. def create(self, data):
  12. user = User.objects.create(**data)
  13. user.set_password(data.get('password'))
  14. user.save()
  15. # 补充生成记录登录状态的token
  16. jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
  17. jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
  18. payload = jwt_payload_handler(user)
  19. token = jwt_encode_handler(payload)
  20. user.token = token
  21. return user

users/serializers.py 使用Serializer的create方法创建token

ContractedBlock.gif ExpandedBlockStart.gif

  1. from django.contrib import admin
  2. from django.urls import path,re_path,include
  3. from users import views
  4. from rest_framework_jwt.views import obtain_jwt_token # 验证密码后返回token
  5. urlpatterns = [
  6. path('admin/', admin.site.urls),
  7. path('register/', views.RegisterView.as_view(), name='register'), # 注册用户
  8. path('login/', obtain_jwt_token,name='login'), # 用户登录后返回token
  9. path('user/list/', views.UserList.as_view(), name='register'), # 测试需要携带token才能访问
  10. ]

urls.py

ContractedBlock.gif ExpandedBlockStart.gif

  1. import json
  2. from rest_framework.views import APIView
  3. from rest_framework.views import Response
  4. from rest_framework.permissions import IsAuthenticated
  5. from rest_framework_jwt.authentication import JSONWebTokenAuthentication
  6. from users.serializers import UserSerializer
  7. # 用户注册
  8. class RegisterView(APIView):
  9. def post(self, request, *args, **kwargs):
  10. serializer = UserSerializer(data=request.data)
  11. if serializer.is_valid():
  12. serializer.save()
  13. return Response(serializer.data, status=201)
  14. return Response(serializer.error, status=400)
  15. # 测试必须携带token才能访问接口
  16. class UserList(APIView):
  17. permission_classes = [IsAuthenticated] # 接口中加权限
  18. authentication_classes = [JSONWebTokenAuthentication]
  19. def get(self,request, *args, **kwargs):
  20. print(request.META.get('HTTP_AUTHORIZATION', None))
  21. return Response({
  22. 'name':'zhangsan'})
  23. def post(self,request, *args, **kwargs):
  24. return Response({
  25. 'name':'zhangsan'})

users/views.py

  1080958-20190617224344976-736249891.png 1080958-20190617224458449-467928512.png 1080958-20190617224728406-311632406.png

  1. # 通过用户token获取用户信息
  2. from rest_framework_jwt.utils import jwt_decode_handler
  3. toke_user = jwt_decode_handler(token)
  4. # {'user_id': 2, 'username': 'lisi', 'exp': 1561504444, 'email': ''}

1111

转载于:https://www.cnblogs.com/xiaonq/p/10987889.html

发表评论

表情:
评论列表 (有 0 条评论,379人围观)

还没有评论,来说两句吧...

相关阅读