drf学习-4

一、drf入门流程

  • 前后端开发模式
  • API接口
  • postman使用
  • 序列化和反序列化
  • restful规范
  • drf:第三方app—快速实现符合restful规范的接口
  • 以后写的都是视图类 都是继承APIView及其子类
  • cbv的执行流程

    -路由中:视图类.(as_view)——View的as_view类的绑定方法——闭包函数view

    -请求来了:执行闭包函数view(request)——self.dispatch(request,*args,**kwargs)

    -View.dispatch:根据请求的方式,执行视图函数中以请求方式命名的方法

补充小知识点:

  反射:通过字符串动态的获取,设置,判断,对象中的属性或者方法

  -getattr  res=getattr(self,'run',None)

  -setattr  setattr(self,'speak',内存地址)  self.speak()

  -hasattr  hasattr('self','run')

  • APIView继承了View,执行流程

  -APIView的as_view了:1、调用父类的as_view  2、去掉了csrf

  -请求来了 执行View的as_view的闭包view——dispatch

  -APIView的dispatch

    -1、包装了新的request

    -2、在执行视图函数之前:执行了三大认证

    -3、执行了视图函数:请求方式是什么,就执行视图函数中得什么方法

    -4、全局异常捕获:全局异常,统一返回格式

  • 序列化类

    -Serializer

    -ModelSerializer

    -序列化

    -反序列化

    -校验

  • 请求与响应

    -Request类:属性和方法

    -Response类

  • 视图层(2基类、5个扩展类、9个子类、视图集)
  • 路由的使用
  • 认证、频率、权限
  • 过滤、排序、分页
  • 全局异常处理
  • 接口文档:自定生成,自己写
  • 前后端分离:jwt认证方式—登录
  • 公司内部:RBAC
  • django:admin美化

二、drf之请求与响应

2.1 Request和Response类

继承APIView后,请求对象:requets—每一次请求都是一个新的request

Request类:属性或方法

  -data:POST、PUT、PATCH请求方式解析后的数据

    原生django,put提交的数据在request.POST中是取不到的

  -query_params

    其他的用起来跟之前一样用(FILES,method,path...)—底层原理__getattr__

Response类

掌握项

  data=None  字典、列表—序列化成json格式字符串,返回给前端(放在http响应的body中)

  status=None  http响应的状态码,默认是200,201

    drf把所有的http响应状态码都做成了常量,可以直接导进来用

  headers=None  http的响应头、字典 {name:curry}

    原生django要在响应头中加数据

      res=JsonResponse(d)

      res['xxx']='ooo'

      return res

了解项

  template_name = None   在浏览器中看到好看的页面,指定的模板

  content_type = None   响应的编码格式(json)

2.2drf能够解析的请求编码,响应编码

请求编码

默认解析

  urlencoded

  form_data

  json

那么问题来了,为什么会默认解析呢?

其实是通过配置完成:项目中没有配置,是在drf内置的配置文件中提前配好了

drf也是有两套,一套是项目中的配置(settings.py),一套是默认的配置

drf的配置文件settings.py中有DEFAULT_PARSER_CLASSES(默认的解析类)

    'rest_framework.parsers.JSONParser',       可以解析json格式
    'rest_framework.parsers.FormParser',        可以解析urlencoded格式
    'rest_framework.parsers.MultiPartParser'   可以解析form-data格式

自定义我们的接口接受什么数据格式?一共两个方式

方式一、全局配置

在项目配置文件settings.py中修改配置,以后所有的接口都遵循这个配置
    REST_FRAMEWORK = {
                'DEFAULT_PARSER_CLASSES': [
                    'rest_framework.parsers.JSONParser',
                    'rest_framework.parsers.FormParser',
                    'rest_framework.parsers.MultiPartParser',
                ],
            }
     '''不用哪个数据格式就把他注释掉就可以实现了'''

方式二、局部配置

方式二:局部配置
class TestView(APIView):
    parser_classes = [JSONParser, FormParser, MultiPartParser]
    '''视图类中固定写法,用哪个数据格式就写在中括号里'''

总结:

解析类的使用顺序:优先用视图类自己的,然后用项目配置文件,最后用内置的

  实际项目如何配置

   -基本上都运行JSONParser,FormParser

  -如果上传文件只允许MultiPartParser

响应编码

如果用浏览器,就能看到好看的样子,如果用postman看到json格式

  -默认请情况下,响应的编码是根据客户端类型决定的

# 全局配置:在项目的配置文件
    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': [
            'rest_framework.renderers.JSONRenderer', # json格式
            'rest_framework.renderers.BrowsableAPIRenderer', #浏览器的格式
          ]
      }

# 局部配置:
class TestView(APIView):
    renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
    
实际编码中,响应一般不配置,就用默认的。

drf之视图组件

由于drf提供了一个顶层的视图类APIView,咱们可以通过继承APIView写视图类,后期咱们要写的代码可能重复代码比较多,就可以使用面向对象的继承,封装。

两个视图基类

  • APIView
    rest_framework.views.APIView
    
    APIView是REST framework提供的所有视图的基类,继承自Django的View父类。
    
    APIView与View的不同之处在于:
    1)传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
    2)视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
    3)任何APIException异常都会被捕获到,并且处理成合适的响应信息;
    4)在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
  • GenericAPIView
GenericAPIView继承了APIView

类属性:
    1)queryset 指明使用的数据查询集
    queryset = User.objects.all()
    2)serializer_class 指明视图使用的序列化器
    serializer_class = UserSerializer

方法:
    self.get_object()      # 根据pk获取单个数据
    self.get_serializer()  # 获取要使用的序列化类
    self.get_queryset()  # 获取所有要序列化数据
  • 基于APIView写5个接口
from rest_framework.views import APIView
class UserView(APIView):
    def get(self, request):
        book_list = User.objects.all()
        ser = UserSerializer(instance=book_list, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = UserSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': "新增成功"}, status=201)
        else:
            return Response({'code': 101, 'msg': ser.errors})


class UserDetailView(APIView):
    def get(self, request, pk):
        book = User.objects.filter(pk=pk).first()
        ser = UserSerializer(instance=book)
        return Response(ser.data)

    def put(self, request, pk):
        book = User.objects.filter(pk=pk).first()
        ser = UserSerializer(instance=book, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': "修改成功"}, status=201)
        else:
            return Response({'code': 101, 'msg': ser.errors})

    def delete(self, request, pk):
        User.objects.filter(pk=pk).delete()
        return Response('')
  • 基于GenericAPIView写5个接口
    from rest_framework.generics import GenericAPIView
    class UserView(GenericAPIView):
        queryset = User.objects.all()
        serializer_class = UserSerializer
    
        def get(self, request):
            book_list = self.get_queryset()
            ser = self.get_serializer(instance=book_list, many=True)
            return Response(ser.data)
    
        def post(self, request):
            ser = self.get_serializer(data=request.data)
            if ser.is_valid():
                ser.save()
                return Response({'code': 100, 'msg': "新增成功"}, status=201)
            else:
                return Response({'code': 101, 'msg': ser.errors})
    
    
    class UserDetailView(GenericAPIView):
        queryset = User.objects.all()
        serializer_class = UserSerializer
        def get(self, request, pk):
            book = self.get_object()
            ser = self.get_serializer(instance=book)
            return Response(ser.data)
    
        def put(self, request, pk):
            book = self.get_object()
            ser = self.get_serializer(instance=book, data=request.data)
            if ser.is_valid():
                ser.save()
                return Response({'code': 100, 'msg': "修改成功"}, status=201)
            else:
                return Response({'code': 101, 'msg': ser.errors})
    
        def delete(self, request, pk):
            self.get_queryset().filter(pk=pk).delete()
            return Response('')

    

posted @ 2022-09-29 21:20  初学者-11  阅读(56)  评论(0编辑  收藏  举报