首页 > 其他分享 >drf学习笔记

drf学习笔记

时间:2022-09-26 21:00:24浏览次数:50  
标签:APIView self request 笔记 django 学习 序列化 data drf

昨日内容回顾

http协议版本区别:

0.9版本:每个http请求都是一个tcp的链接
1.1版本:keep-alvie, 每个http请求可以使用同一个tcp
2.x版本:同一个tcp的包,可能是多个http请求,多路复用

今日内容概要

  • APIView基本使用
  • APIView源码分析
  • Request类源码分析
  • 序列化组件介绍
  • 序列化组件基本使用
  • 反序列化

今日内容详细

APIView基本使用

drf:是一个第三方的app,是需要注册的,去settings里添加INSTALLED_APPS。只能在django上使用。

安装了drf后,导入一个视图类APIView,所有后期要使用drf写视图类,都是继承APIView及其子类。

INSTALLED_APPS = [
    'rest_framework',   # 一定不要忘了注册
]
"""
需要注意点的点:
    app要加上逗号
    不可以使用使用三引号加注释
"""

使用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})  # 只能序列化字典和列表,

使用APIView+drf的Response写

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):   # 这个request是新的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 Response(res_list)

补充知识:

django项目中app的作用:django是一个大而全的框架,内置了很多的app帮我们完成了很多的事情,比如说数据库的迁移自动生成的很多表。

INSTALLED_APPS = [
    'django.contrib.admin',  # 后台管理,系统自带后台管理admin
    'django.contrib.auth',   # 权限管理--》生成6张表
    'django.contrib.contenttypes',# 对所有app的表进行记录的
    'django.contrib.sessions',   # session功能--》django-session表---》app
    'django.contrib.messages',  # django消息框架---》flask的闪现
    'django.contrib.staticfiles', #  静态资源
    'rest_framework',   # 一定不要忘了注册
]

APIView源码分析

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

一旦继承了APIView从路由入口

路由配置跟之前继承View是一样的----》找视图类的as_view---》【APIView的as_view】

path('books/', BookView.as_view()),

views.BookViwe.as_view()的执行结果,是函数内存地址----》view这个函数的内存地址

但是现在的as_view已经不是django原生View的as_view了,而是drf的APIView的as_view了。因为自己写的类继承了APIView,面向对象中 属性查找顺序是先从自己找,再从产生对象的类中找,再去类的父类中找,所以先找到的是APIView里重写的as_view方法。

@classmethod
def as_view(cls, **initkwargs):  # as_view是django的View的派生方法
    # 又调用了父类(View)的as_view
    view = super().as_view(**initkwargs)
    # csrf_exempt(view)的作用就是把csrf校验全去掉了,之后就不需要去注释掉中间件中的csrf了,就类似于给view加了一个csrf_exempt装饰器。
     '''
     从此以后,所有的请求都没有csrf的校验了
     在函数上加装饰器
     @csrf_exempt
     def index(request):
         pass
     本质等同于 index=csrf_exempt(index)
      '''
     # 它就是装饰器的本质:把被装饰的函数当做参数,传入装饰器函数,返回值赋值给被装饰的函数
     return csrf_exempt(view)

重点:view还是调用的View里的view,只是不需要处理csrf了。

dispatch已经不是django原生View的dispatch了,是drf的APIView的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
    self.request = request
    try:  # 捕获了异常
        # 内部执行了三大认证:认证(登陆认证),频率(1分钟只能访问接口3次),权限(普通用户不能访问,超级用户才能访问)
        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)
    # 包装了response对象,响应对象,浏览器看到好看的样子,postman只看到json
    self.response = self.finalize_response(request, response, *args, **kwargs)
    return self.response

重点:

1.只要继承APIView都没有csrf的认证了

2.以后视图类中使用的request对象,已经变成了drf提供的Request类的对象了

rest_framework.request.Request   # 以后新的request
django.core.handlers.wsgi.WSGIRequest  # django原来的

3.执行视图类的方法之前,执行了3大认证(认证,权限,频率)、

4.在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理

Request类源码分析

以后视图类中使用的request对象,是rest_framework.request.Request的对象。

# 类中有个魔法方法:__getattr__    对象.属性,属性不存在会触发它的执行
# 还有self.__dict__(名称空间),对象点属性都是在__dict__里面取,没有触发__getattr__执行
def __getattr__(self, attr): # 如果取的属性不存在会去原生django的request对象中取出来
    try:
        #反射:根据字符串获取属性或方法,self._request 是原来的request
        return getattr(self._request, attr)
    except AttributeError:
        return self.__getattribute__(attr)


1.以后用的所有属性或方法,直接用就可以了,跟之前一样---》(通过反射去原来的request中取的)
2.新的request内部有个老的request,就是 request._request
3.新的request有个data方法,被property装饰了,变成了数据属性用
    -以后body体中提交的数据,都从这里取(request.POST)
    -urlencoded,form-data:提交的数据在request.POST中
    -json格式提交的数据,在requets.POST中没有,它在request.body中
    -现在无论那种格式,都从request.data中取
4.新的request有个query_params方法,包装成了数据属性:get请求提交的参数,等同于request._request.GET 或  request.GET
5.取文件是从request.FILES中取,跟之前一样,但是人家重写了

# 验证 原生requets.POST 只有urlencoded和form-data格式提交的数据,json格式提交的数据在body中,拿出来自己处理,但是drf的request中有个data,data中可以取到任意编码提交的数据
# request.data  有时候是(urlencoded,form-data)QueryDict,有时候(json)是字典

补充:什么是魔法方法?
1 在类中只要以__开头,__结尾的都称之为魔法方法
2 这种方法不需要手动调用,某种情况会自动触发
3 你学过的: __init__,__str__,__call__,......

序列化组件介绍

1.序列化组件是什么?

drf提供的一个类,我们继承它,写自己的类。

2.序列化组件有什么用?

是用来序列化queryset或单个对象的。

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

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

定义一个序列化类

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

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

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

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)

使用序列化类,序列化单条数据

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

反序列化(新增,修改)

新增,修改---》前端传入的数据,要校验---》反序列化,完成数据校验功能

新增

# 序列化类
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


# 视图类
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()

    # 重写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


# 视图类
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)

标签:APIView,self,request,笔记,django,学习,序列化,data,drf
From: https://www.cnblogs.com/wwjjll/p/16732457.html

相关文章

  • 线性表前期学习
         ......
  • 九月第一篇关于《程序员修炼之道:从小工到专家》的阅读笔记
    《程序员修炼之道:从小工到专家》阅读笔记这本书是自从进入软件工程系以来所阅读的第二本书,本篇是九月的第一篇阅读笔记,希望在这里记录一些我的感悟。 首先从整体来看,这......
  • 集合笔记记录
    目录Collection基础概念List1.ArrayList1.1ArrayList的特点:1.2ArrayList构造源码分析:2.LinedList2.1基本介绍2.2LinkedList源码分析2.2.1构造源码2.2.2添加方......
  • 51单片机学习日志一:流水灯和定时器
    单片机最小系统的三要素就是电源、晶振、复位电路单片机复位一般是3种情况:上电复位、手动复位、程序自动复位。没有电压差就不会产生电流一、sbit在单片机中的使用C5......
  • Python学习之路04
    今日内容总结1.基本数据类型布尔值bool布尔值是用来判断对错的,我们主要用于流程控制中布尔值只有两种表达方式:True/Falseps:要首字母大写Python中的所有数据都是由布......
  • 【XML】学习笔记第四章-schema
    Schema概述作用与DTD相比Schema的优势基础命名空间:模式引用方法通过xsi:noNamespaceSchemaLocation引入通过xsi:shemaLocation引入Schema的语法结构定......
  • 【XML】学习笔记第三章-namesapce
    目录命名空间命名空间概述命名空间语法命名空间的声明命名空间作用域对命名空间的使用元素对命名空间的使用属性对命名空间的使用DTD对命名空间的支持命名空间命名空间概......
  • 【XML】学习笔记第二章-dtd
    目录XML-DTDDTD语句基本声明语句引用外部DTDDTD元素四种元素类型元素定义关键字修饰符号DTD中的属性属性修饰属性类型DTD中的实体和符号符号坑XML-DTDDTD(DocumentTypeD......
  • 学习python-Day64
    回顾补充知识http请求应用层:基于tcp/ip之上是进行网络传输,广泛用于前后端的交互请求协议:请求首行请求方式:get、post,请求地址:get携带数据,请求协议,请求版本......
  • Flask学习笔记(三)-jinja2 模板入门
    一、表达式jinja2是一个被广泛使用的模板引擎,其设计思想源自于django模板引擎,jinja2扩展了语法,增加了强大的功能,被flask选为内置的模板语言示例的目录结构如下./├─......