DRF request对象、 Serializer

 

  • CBV的源码分析

  • drf之APIView的执行流程分析

  • drf的Request对象分析

  • 序列化类Serializer的使用

 

CBV的源码分析

#注意django2.x 路由层不一样了 不用url  用path   re_path等于django1.x的url(不推荐使用)
from django.urls import path
	#views.IndexView.as_view() 等于 继承的View里面的asview里面的view的内存地址
    path('index/',views.IndexView.as_view())     #路由方法里第二个参数就是内存地址
    

大概流程  入口 在urls  里面调用量.as_view() 属于调用  这个方法类里没有 去父类找 ,发现as_view方法return一个view 的内存地址  所以 urls里面第二个参数就是这个view的内存地址 然后看这个view 里面 生成了一个self=(**initkwargs)  所以  self 是对象  是 传进来的类的对象   然后发现view  return了一个self.dispatch, 先去对象找 再去生成这个对象的类找 最后父类找 在父类找到了,这个dispatch方法里面先把请求方法转小写 并判断是不是在一个变量里 这个变量里存放了 get post put patch dlete 等等 如果在 则会利用反射得到一个内存地址 ,判断self 有没有这个请求的方法 并赋值 没有则调用一个报错方法 最后return 这个内存地址(request, *args, **kwargs) 调用
主要核心为dispatch
  def dispatch(self, request, *args, **kwargs):
        #判断请求方法转小写是不是在那八个方法里
        if request.method.lower() in self.http_method_names:
            #通过反射得到一个内存地址
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            # handler = getattr(self, 'get', self.http_method_not_allowed) # handler就是函数内存地址
        else:
            handler = self.http_method_not_allowed
        # get, post, put ...
        return handler(request, *args, **kwargs) # get(request, *args, **kwargs), post()

drf之APIView的执行流程分析

#注册 注册 注册 因为rest_framwork是应用 用Response 要记得注册不然他没有页面 其实是返回来Json数据


# 数据库迁移:
	makemigrations app01 # 后面可以加应用名,代表只迁移这个应用下的数据
# 如果不加应用名,代表迁移所有应用的数据

#只要导入了rest_framework里面的东西 都要继承APIView ,APIView也继承了View  所以 CBV必须继承View  

#推导过程   执行了ApiView里面的as_view
@classmethod
    def as_view(cls, **initkwargs):
 		# View类的as_view()
        view = super().as_view(**initkwargs) #view:是View里面的as_view里面的view的函数内存地址
        return csrf_exempt(view) # 去掉了csrf的验证, 跟之前的加在视图函数上一毛一样  等同与view上面加个跳过csrf验证装饰器  return view的内存地址
    #所有apiview都没有csrf认证
    
#get请求 如何运行
	#走View里面的as_view里面的view函数 返回了self.dispatch   这个self 是 继承apiview的类产生的对象
    #去的时候apiview的dispatch
     def view(request, *args, **kwargs):
            # self 就是IndexView类的对象
            self = cls(**initkwargs) # IndexView()
            return self.dispatch(request, *args, **kwargs)
        
# APIView的源码分析:
    def dispatch(self, request, *args, **kwargs):
        # 它封装了新的request, 后面的request还是Django的request
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request  # drf的request

        try:
            # 这个里面做了三大认证: 认证,权限,频率
            self.initial(request, *args, **kwargs)

        except Exception as exc:
            response = self.handle_exception(exc)

        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
 # 重点:
	APIView做了三件事:
    	1. 把Django的request封装了新的request,drf的request
        	以后你在视图函数中,在使用request,就是新的request了。
        2. 进行了三大认证:
        	self.perform_authentication(request)  # 认证
            self.check_permissions(request)    # 权限
            self.check_throttles(request)   # 频率
       3. 做了全局的异常处理
    
    # 以后,只要继承了APIView, 在视图函数中使用的request都是新的request。
    在执行视图函数之前,进行了三大认证。

drf的request对象分析

#  request = self.initialize_request(request, *args, **kwargs)  老的request 执行了一个方法 变成了新的request
def initialize_request(self, request, *args, **kwargs):
        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
    
    

class Request:
    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        assert isinstance(request, HttpRequest), (
            'The `request` argument must be an instance of '
            '`django.http.HttpRequest`, not `{}.{}`.'
            .format(request.__class__.__module__, request.__class__.__name__)
        )
		# 重点再下面一句话
        self._request = request   #老的request 值给了_request
        
 # 为什么新的request和老的request使用起来一模一样?
是因为再Request类中重写了__getattr__方法
 def __getattr__(self, attr):
        try:
            #通过反射 去老的request 取出属性或方法
            return getattr(self._request, attr)
        except AttributeError:
            return self.__getattribute__(attr)
        
  # 新的request有什么特性?
	多了一个data属性 request.data  感觉是个数据属性 其实是个方法
	针对post请求的三种编码格式都可以从data属性中取到 urlencoded  formdata json

序列化类Seaializer的使用

自定义一个serializer.py文件
#如果想使用序列化 需要继承Serializer
from rest_framework import serializers
class BookSerialzer(serializers.Serialzer)
	title=serializers.CharField()
	price=serializers.IntegerField()

    
#views

class BookView(APIView):
    def get(self, request):
        book_list = models.Book.objects.all()
        print(request.data)
        #多个数据加many=True
        ser = Bookserializer(instance=book_list, many=True)
        return Response(ser.data)



class BookDetView(APIView):
    def get(self, request,pk):
        book = models.Book.objects.filter(pk=pk).first()
        bookser = Bookserializer(book)  #many 多个数据加
        return Response(bookser.data)

Django2默认支持以下5个转化器:

str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int,匹配正整数,包含0。
slug,匹配字母、数字以及横杠、下划线组成的字符串。
uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
posted @ 2021-12-18 17:07  迪迦张  阅读(41)  评论(0编辑  收藏  举报