首页 > 其他分享 >【2022.9.26】drf(2)

【2022.9.26】drf(2)

时间:2022-09-26 22:25:06浏览次数:65  
标签:26 APIView self request book 2022.9 序列化 data drf

今日学习内容

  • 1 APIView基本使用

    • 1.1 使用View+JsonResponse写
    • 1.2 使用APIView+drf的Response写(不要忘了注册rest_framework这个app)
  • 2 APIView源码分析

  • 3 Request类源码分析

    • 3.1 Request类源码分析
  • 4 序列化组件基本使用(查询所有,查询单个)

    • 4.1 定义一个序列化类
    • 4.2 使用序列化类,序列化多条数据
    • 4.3 使用序列化类,序列化单挑数据
  • 5 反序列化(新增,修改)

    • 5.1 新增(视图类)

    • 5.2 修改(视图类)

1 APIView基本使用

# drf:是一个第三方的app,只能在djagno上使用
# 安装了drf后,导入一个视图类APIView,所有后期要使用drf写视图类,都是继承APIView及其子类

# 获取所有图书接口

1.1 使用View+JsonResponse写

class BookView(View):
    def get(self, request):
        print(type(request))
        book_list = Book.objects.all()
        # book_list是queryset对象不能直接序列化,只能通过for循环一个个拼成列表套字典的形式
        res_list = []
        for book in book_list:
            res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return JsonResponse(res_list,safe=False,json_dumps_params={'ensure_ascii':False})  # 只能序列化字典和列表,

1.2 使用APIView+drf的Response写(不要忘了注册rest_framework这个app)

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request

class BookView(APIView):  # APIView继承自django的View
    def get(self, request):
        # print(type(self.request))  # 新的request
        # print(type(request))
        print(request._request)
        print(type(request._request)) #django.core.handlers.wsgi.WSGIRequest

        # print(request.method)  # get
        # print(request.path)  # /books/
        # print(request.GET)  # 原来的get请求提交的参数
        # print(request.POST)  # 原来post请求提交的参数

        book_list = Book.objects.all()
        # book_list是queryset对象不能直接序列化,只能通过for循环一个个拼成列表套字典的形式
        res_list = []
        for book in book_list:
            res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return Response(res_list)

2 APIView源码分析

# 视图类继承APIView后,执行流程就发生了变化,这个变化就是整个的drf的执行流程

# 一旦继承了APIView入口
	-路由配置跟之前继承View是一样的----》找视图类的as_view---》【APIView的as_view】
        @classmethod
        def as_view(cls, **initkwargs):
            # 又调用了父类(View)的as_view
            view = super().as_view(**initkwargs)
            '''
            # 从此以后,所有的请求都没有csrf的校验了
            # 在函数上加装饰器
            @csrf_exempt
            def index(request):
                pass
            本质等同于 index=csrf_exempt(index)
            '''
            return csrf_exempt(view)
        
    -请求来了,路由匹配成功会执行 View类的的as_view类方法内的view闭包函数(但是没有了csrf认证),
    -真正的执行,执行self.dispatch---->APIView的dispatch  【这是重点】
     def dispatch(self, request, *args, **kwargs):
        # 参数的request是原来的django原生的request
        # 下面的request,变成了drf提供的Request类的对象---》return Request(。。。)
        request = self.initialize_request(request, *args, **kwargs)
        # self 是视图类的对象,视图类对象.request=request 新的request
        self.request = request
        try:
            # 执行了认证,频率,权限 [不读]
            self.initial(request, *args, **kwargs)
            # 原来的View的dispatch的东西
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                 self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            response = handler(request, *args, **kwargs)
        except Exception as exc:
            # 如果出了异常,捕获异常,处理异常,正常返回
            # 在执行三大认证和视图类中方法过程中,如果出了异常,是能被捕获并处理的---》全局异常的处理
            response = self.handle_exception(exc)
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
    
    
    
    # 总结:
    	1 只要继承APIView都没有csrf的认证了
        2 以后视图类中使用的request对象,已经变成了drf提供的Request类的对象了
        3 执行视图类的方法之前,执行了3大认证(认证,权限,频率)
        4 在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理

3 Request类源码分析

#1  视图类中使用的request对象,已经变成了drf提供的Request类的对象了
	-原生djagno 的request是这个类的对象:django.core.handlers.wsgi.WSGIRequest
    -drf的request是这个类的对象:rest_framework.request.Request
    
#2 request已经不是原来的request了,还能像原来的request一样使用吗?
	-用起来,像之前一样
        print(request.method)  # get
        print(request.path)  # /books/
        print(request.GET)   # 原来的get请求提交的参数
        print(request.POST)  # 原来post请求提交的参数
        
        
#3 Request的源码分析:rest_framework.request.Request
	-类中有个魔法方法:__getattr__    对象.属性,属性不存在会触发它的执行
	def __getattr__(self, attr): # 如果取的属性不存在会去原生django的request对象中取出来
        try:
            #反射:根据字符串获取属性或方法,self._request 是原来的request
            return getattr(self._request, attr)
        except AttributeError:
            return self.__getattribute__(attr)
        
    -以后用的所有属性或方法,直接用就可以了---》(通过反射去原来的request中取的)
    
    -新的request内部有个老的request,就是 request._request
    
    -data 是个方法,被property装饰了,变成了数据属性用
    	-以后body体中提交的数据,都从这里取(request.POST)
        -urlencoded,form-data:提交的数据在request.POST中
        -json格式提交的数据,在requets.POST中没有,它在request.body中
    	-现在无论那种格式,都从request.data中取
    -query_params:get请求提交的参数,等同于request._request.GET 或  request.GET
    -其他:取文件也是从request.FILES中取,跟之前一样
    
    
    
# 验证 原生requets.POST 只有urlencoded和form-data格式提交的数据,json格式提交的数据在body中,拿出来自己处理,但是drf的request中有个data,data中可以取到任意编码提交的数据
    
# request.data  有时候是(urlencoded,form-data)QueryDict,有时候(json)是字典
    
# 4 什么是魔法方法?
	1 在类中只要以__开头,__结尾的都称之为魔法方法
    2 这种方法不需要手动调用,某种情况会自动触发
    3 你学过的: __init__,__str__,__call__,......

3 序列化组件介绍

#是什么?drf提供的一个类,我们继承它,写自己的类
# 有什么用?就是用来序列化qs或单个对象的

# 获取所有图书接口----》qs,单个book对象转成json格式字符串,给前端---》序列化
	-使用for循环,列表套字典拼接的
  


# drf提供了一种可以快速实现序列化的类:序列化类

4 序列化组件基本使用(查询所有,查询单个)

4.1 定义一个序列化类

# 写序列化类:给book进行序列化
# from rest_framework.serializers import Serializer
from rest_framework import serializers


class BookSerializer(serializers.Serializer):
    # 要序列化的字段    有很多字段类,字段类有很多字段属性
    name = serializers.CharField()  # 字段类
    # price = serializers.CharField()
    publish = serializers.CharField()

4.2 使用序列化类,序列化多条数据

class BookView(APIView):  # APIView继承自django的View
    def get(self, request):
        book_list = Book.objects.all()
        # instance表示要序列化的数据,many=True表示序列化多条(instance是qs对象,一定要传many=True)
        ser = BookSerializer(instance=book_list, many=True)

        return Response(ser.data)

4.3 使用序列化类,序列化单挑数据

class BookDetailView(APIView):
    def get(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book)
        return Response(ser.data)

5 反序列化(新增,修改)

# 新增,修改---》前端传入的数据,要校验---》序列化类有数据校验功能

5.1 新增

视图类

class BookView(APIView):  # APIView继承自django的View
    def post(self, request):
        # 前端传递数据,从request.data取出来
        ser = BookSerializer(data=request.data)
        if ser.is_valid():  # 表示校验前端传入的数据   没有写校验规则,现在等于没校验
            ser.save()  # 再写东西,这里会报错  调用save会触发BookSerializer的save方法,判断了,如果instance有值执行update,没有值执行create
            return Response(ser.data)
        else:
            return Response(ser.errors)

序列化类

class BookSerializer(serializers.Serializer):
    # 要序列化的字段    有很多字段类,字段类有很多字段属性
    name = serializers.CharField()  # 字段类
    price = serializers.CharField()
    publish = serializers.CharField()

    # 重写create方法,
    def create(self, validated_data):
        res = Book.objects.create(**validated_data)
        return res

5.2 修改

视图类

class BookDetailView(APIView):
    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        # 前端传递数据,从request.data取出来
        ser = BookSerializer(instance=book, data=request.data)
        if ser.is_valid():  # 表示校验前端传入的数据   没有写校验规则,现在等于没校验
            ser.save()  # 再写东西,这里会报错  调用save会触发BookSerializer的save方法,判断了,如果instance有值执行update,没有值执行create
            return Response(ser.data)
        else:
            return Response(ser.errors)

序列化类

class BookSerializer(serializers.Serializer):
    # 要序列化的字段    有很多字段类,字段类有很多字段属性
    name = serializers.CharField()  # 字段类
    price = serializers.CharField()
    publish = serializers.CharField()

    # 重写update
    def update(self, instance, validated_data):
        # instance要修改的对象
        # validated_data 校验过后的数据
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        instance.publish = validated_data.get('publish')
        instance.save()
        return instance

练习

  • 第一题
1. http/0.9:只有GET命令,服务器只能回应HTML格式字符串 
2.http/1.0:每个TCP连接只能发送一个请求,还要发送请求需要再次连接 
3.http/1.1:可以持久连接,TCP连接默认不关闭,可以被多个请求复用;keep-alive 
4.http/2:复用TCP协议,在一个连接里客户端与浏览器都可以同时发送多个请求或回应,不用按照顺序

  • 第二题
1. Accept:设置接受的内容类型 
2. Accept-Charset:设置接受的字符编码 
3. Accept-Encoding:设置支持的内容编码的优先级顺序 
4. Accept-Language:设置接受的语言 
5.Connection:设置当前事务完成后,是否会关闭网络连接 
6.Connection-Length:设置请求体的字节长度 
7.Content-Type:设置请求体的MIME类型 
8. referer:包含了当前请求页面的来源页面地址
9.Cookie:设置服务器使用set-cookie发送的http cookie

标签:26,APIView,self,request,book,2022.9,序列化,data,drf
From: https://www.cnblogs.com/55wym/p/16732721.html

相关文章

  • drf2-apiView源码-基本使用-request类源码分析-序列化组件-基本使用-反序列化
    apiView基本使用apiview源码分析request类源码分析序列化组件介绍序列化组件基本使用(查询所有,查询单个)反序列化(新增,修改)ApiView基本使用drf是一个第三方的app,只能......
  • 做题记录整理dp13 P5664 [CSP-S2019] Emiya 家今天的饭(2022/9/26)
    P5664[CSP-S2019]Emiya家今天的饭终于遇到一个我感觉在考场上有可做出来的题了。。。唯一想不到的就是最开始的容斥(也就是说还是看了题解。。。),如果容斥想到的话其他......
  • 【2022-09-26】DRF从入门到入土(二)
    DRF从入门到入土(二)一、APIView基本使用使用view+JsonResponse获取所有图书接口安装drf:pip3installdjangorestframeworksettings.py注册app:'rest_framework......
  • 做题记录整理dp12 P7961 [NOIP2021] 数列(2022/9/26)
    P7961[NOIP2021]数列当时在考场上对于拿部分分这个感念不是很清晰,所以当时连暴力分都没拿。。。事实上这题在看了题解之后还是有很多地方没搞明白,比如最后统计答案,为什......
  • Test 2022.09.26
    今天是水题专场T1扩散感觉这种要么就是二分答案网络流,要么就是最小生成树,(随便口胡的),树德保留节目了属于是。分析简简单单一眼最小生成树(又是),边权就是两个点之间存在公......
  • drf学习笔记
    昨日内容回顾http协议版本区别:0.9版本:每个http请求都是一个tcp的链接1.1版本:keep-alvie,每个http请求可以使用同一个tcp2.x版本:同一个tcp的包,可能是多个http请求,多路......
  • 9.26水题大赏
    2022-9-26T1扩散明显可以二分答案,也可以用最小生成树去做。考试时写的最小生成树,每两个点连一条边权为这两个点的曼哈顿距离。每次找最小的距离,\(\div2+1\)后更新\(ans......
  • 37th 2022/8/12 模拟赛总结26
    这次真不可理喻这次T1是差分约束,这次,得完全弄懂T1,因为之前考过差分约束,但一直都不会,改了题后却没有印象,这次做出总结:就是一个将输入改为一条形同松弛原理的式子,如:\(X_i-X......
  • drf之APIView
    一、APIView的基本使用#drf:是一个第三方的app,只能在djagno上使用#安装了drf后,导入一个视图类APIView,所有后期要使用drf写视图类,都是继承APIView及其子类#现在通过......
  • 9.26-CSP-S模拟12
    T1开挂比较水的贪心题,可以证明一定只包含不相交,拿个栈就很好做了。点击查看代码#include<bits/stdc++.h>typedeflonglongll;typedefunsignedlonglongull;ty......