编程语言
首页 > 编程语言> > CBV源码的一个分析 APIView的基本使用 APIView执行流程分析 序列化类Serializer的使用

CBV源码的一个分析 APIView的基本使用 APIView执行流程分析 序列化类Serializer的使用

作者:互联网

昨日回顾

# 1 web 前后端开发模式
	-混合开发:既要写前端,又要写后端----》全栈工程师
  -前后端分离:前端一个项目,后端一个项目,分别不同的组来做,api接口,数据通信
  
  -模板语法:渲染在后端完成
  
  -前端用php写的,后端用python写的?
  -php后端语言,跟python同一级,一类东西,在html页面中写模板语法(等同于dtl)
  -有的项目模板中写了php的语法---》他认为php可以写前端--》
  -只有html,css,js能写前端
  
  
# 2 api接口
	-web方向前后端交互的媒介
  -地址---》发送请求---》返回json、xml格式数据
  
# 3 接口测试工具


	-接口写好,测试,不可能使用浏览器测接口---》无法发送delete,post。。。请求
  -jq把难用,长的代码,封装的更短,更好用---》逐渐被弃用了
  -js的ajax,发送---》$.ajax()--->jq的一个方法---》ajax可以有不同的实现
  	-ajax是个概念:使用js,向后端发送http请求,
    	-js写代码实现概念,代码对浏览版本,厂商不兼容,原生js写非常麻烦
      -$.ajax() 具体实现,jq实现的
      -fetch   官方的实现,还有点问题
      -axios   具体实现,第三方实现的
      
  -使用工具---》发送http的请求
  	-postman,postwoman。。。。
    -会如何发送http请求(get,post,delete)
    -如何在请求地址中加数据
    -如何在请求头中加数据
    -如何在请求体中加数据:请求编码  urlencoded,formdata,json
  
  	-如何看返回的状态码,响应体,响应头
    

# 4 restful规范---10条
	-1 https 加密传输
  -2 带api标识
  -3 地址中带版本
  -4 名词复数,不要出现动词    --注册接口,登陆接口
  -5 请求方式决定了行为 get 获取数据,post增加数据,put修改,delete删除数据
  -6 响应中带状态码  http状态码,公司自己的状态码
  -7 响应中带错误信息  msg
  -8 响应中带连接
  -9 请求中带过滤,查询条件
  -10 返回结果符合规范(好的没有遵循):新建:返回新建的  删除:返回空文档
  
  
# 5 drf:djangorestframework--》django的一个app,方便我们快速编写出符合restful规范的接口---》只能用在django---》注意版本,跟django版本,python解释器版本,操作系统环境
	-pip3 install djangorestfamework == 版本
  
# 6 序列化和反序列化
		-序列化:把我们的数据,转成某个格式给别人      read 
  	-反序列化:别人把数据给我们,存到数据库中      write

今日内容详细

CBV源码的一个分析1.1

url:
    urlpatterns = [
    path('admin/', admin.site.urls),
    # 首先他的一个标准的路由是这样写的:path('地址/',函数内存地址)
    #我们这里可能会有疑问views.BookView.as_view()以为加了括号我们都知道是函数执行,难道这不是一个函数结果嘛?
    #对还就是函数结果但是这个函数结果就是执行的内存地址————》也就是这个View函数
    path('books/', views.BookView.as_view()),
]
    # 请求来了---》路由匹配成功----》会执行 这个函数---》view(request)
    最后还执行了dispatch
# view----》self.dispatch(request)
as_view()源码:
def view(request, *args, **kwargs):(*args,**kwargs是有名分组或无名分组的参数)
    return self.dispatch(request, *args, **kwargs)

#dispatch这个方法我们从源码中也可以看出:首先看源码这里的两个重点 
    def dispatch(self, request, *args, **kwargs):
        if request.method.lower() in self.http_method_names:
            # 'get'--->self是视图类的对象--》handler就是你写在视图类中的get方法
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            #如果你请求不合法则无权限访问抛出405异常,如果是 http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']以外的方法则不被允许
            http_method_not_allowed:源码抛出异常如下
            """      logger.warning(
            'Method Not Allowed (%s): %s', request.method, request.path,
            extra={'status_code': 405, 'request': request})  """
            handler = self.http_method_not_allowed
            # 执行get方法---》视图函数的get方法
        return handler(request, *args, **kwargs)
    
  第一个:http_method_names看它的源码之中
  http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']这几个方法我们也都很熟悉,你是什么请求,就会执行视图类中请求名字的方法,
        	# 请求方法变成小写字符串  ,如果是get请求,就是 'get'
      # self.http_method_names  列表 ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    其次再看第二个重点:反射,去对象中,根据字符串,取出方法或属性

APIView的基本使用

from rest_framework.views import APIView#路由
from rest_framework.views import Response#响应对象
from rest_framework.views import Request#请求对象
from rest_framework.authentication import BaseAuthentication #认证

from rest_framework.views import APIView
from rest_framework.views import Response

class BookView(APIView):
    def get(self,request):
        return Response('hello web')
#drf中的相应,Response等同于JasonResponse+HttpResponse结合

# 以后写的cbv要继承 APIView 及其子类
########## drf是个app,需要注册 ##########
INSTALLED_APPS = [
		...
    'rest_framework'   # 一定不要忘了注册
]
INSTALLED_APPS =[]因为他是一个列表所以在这里边写注释的话要用井号,其次在注册写入其他的时候别忘了逗号隔开
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', #  静态资源,
    'app01.apps.App01Config',
    'rest_framework',   # 一定不要忘了注册
   
]
# 由于继承了APIView---》执行APIView的as_view---》执行APIView的dispatch---》内部执行变化了
之所以迁移的时候会有那么多默认的表就是因为这个,把他注册了之后就没了

APIView执行流程分析

#######流程分析
# path('books/', views.BookViwe.as_view())
# views.BookViwe.as_view()的执行结果,是函数内存地址----》view这个函数的内存地址
# 现在的as_view已经不是django原生View的as_view了----》面向对象中 属性查找顺序---》而是drf的APIView的as_view了

#### 路由写法没变----》执行发生了变化 #### 
# 请求来了---》路由匹配成功----》会执行 这个函数---》view(request)
#### 派生方法:子类中重写父类中的方法或者新写方法  叫派生
### 派生类---》子类
    def as_view(cls, **initkwargs):  # as_view是django的View的派生方法
    		# 这个view就是原生django中View类的view,还是原来的view
        view = super().as_view(**initkwargs)
        # csrf_exempt--->去除了所有的csrf---》csrf中间件---》post提交数据,如果不注释---》协带csrf---》以后,无论中间件是否注释,都不需要带了
        # csrf_exempt装饰器装饰视图函数--->本质跟csrf_exempt(view)一毛一样
        # 它就是装饰器的本质:把被装饰的函数当做参数,传入装饰器函数,返回值赋值给被装饰的函数
        return csrf_exempt(view)
      
###### 重点:1 view还是原来的view,2 以后不用管csrf了


# dispatch---》已经不是django原生View的dispatch了,是drf的APIView的dispatch了---》查找顺序的问题
    def dispatch(self, request, *args, **kwargs):
				#1 包装了新的request对象--》以后视图类中用的request对象,就是新的request
        request = self.initialize_request(request, *args, **kwargs)

        try:  # 捕获了异常
          	# 内部执行了三大认证:认证(登陆认证),频率(1分钟只能访问接口3次),权限(普通用户不能访问,超级用户才能访问)
            self.initial(request, *args, **kwargs)
            # 原来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 drf:包装了新的request对象(drf的Request的对象了),已经不是django 的request对象了
  		  # rest_framework.request.Request   以后新的request
        # django.core.handlers.wsgi.WSGIRequest  django原来的
  -2 在执行视图函数之前,执行了三大认证
  -3 处理了全局异常 ---》执行三大认证期间,执行视图函数期间,如果出了错,都能统一处理
  -4 包装了响应对象

5 序列化类Serializer的使用

# pycharm 中集成了 mysql,sqlite的客户端,可以直接使用pycharm连接myslq,sqlite
	-pycharm是用java写的---》能够连接myslq,下一个插件,其实是一个jar包---》jdbc-java提供的连接数据库的接口,但是没有具体实现---》需要下不同的jar包,具体实现,再来连接mysql,sqllite
	-实在用不了
  	-Navicat :收费软件,需要破解,it工作者,自己网上找破解
    -xxx
# 序列化组件--->一个类,可以完成下面的事
  1. 序列化,把模型对象(book,queryset)转换成字典,经过drf的response以后变成json字符串
  2. 反序列化,把客户端发送过来的数据(前端json格式字符串),经过request.data以后变成字典,序列化器可以把字典转成模型,存到数据库
  3. 反序列化,完成数据校验功能---》前端传入的数据,长短,是否是邮箱,手机号。。可以做校验
  
  
# 1 序列化的功能  表中数据,序列化后,以json格式返回给前端

视图类views

from .models import Book
from .serializer import BookSerializer


class BookAPIView(APIView):
    def get(self, request):
         # 取出所有图书的qs对象
        books = Book.objects.all()
        ser = BookSerializer(instance=books, many=True)
        print(ser.data)  # 把qs对象,转成了字典,根据序列化类中你写的字段转的
        return Response(ser.data)
类实例化时的 两个参数:
instance:序列化的对象
many:True 序列化多条

序列化类

from rest_framework import serializers

class BookSerializer(serializers.Serializer):  # 一定要继承Serializer
    # 写要序列化的字段,比如,不想把XX展示给前端去看就直接可以注释掉
    name = serializers.CharField()  # 字段类,跟models中一一对应
    price = serializers.IntegerField()  # 字段类,跟models中一一对应
    publish = serializers.CharField()  # 字段类,跟models中一一对应
    author = serializers.CharField()  # 字段类,跟models中一一对应

序列化类常用字段和字段参数

# 字段类和字段属性

### 字段类:跟models一一对应,但是比它多
# BooleanField 	
# NullBooleanField 	
# CharField 	
# EmailField
# RegexField 
# SlugField 
# URLField 	
# UUIDField 	
# IPAddressField 	
# IntegerField 	
# FloatField 
# DecimalField 
# DateTimeField 	
# DateField 	
# TimeField 	
# ChoiceField 	
# FileField 	
# ImageField 	

------ 以上都是models有的----下面是serializer独有的---
# ListField 	
# DictField 	



#### 字段属性--->写在字段类中的---》干啥用?反序列化校验用的!!!!
## 选项参数
# CharField
max_length 	最大长度
min_lenght 	最小长度
allow_blank 	是否允许为空
trim_whitespace 	是否截断空白字符

# IntegerField
max_value 	最小值
min_value 	最大值

# 通用参数:
### 重点讲
read_only 	表明该字段仅用于序列化输出,默认False
write_only 	表明该字段仅用于反序列化输入,默认False


required 	表明该字段在反序列化时必须输入,默认True
default 	反序列化时使用的默认值
allow_null 	表明该字段是否允许传入None,默认False
error_messages 	包含错误编号与错误信息的字典

标签:APIView,self,request,django,---,源码,序列化,view
来源: https://www.cnblogs.com/ister/p/16380543.html