ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

APIView使用

2022-06-25 16:33:31  阅读:138  来源: 互联网

标签:APIView self request django --- 使用 序列化 view



1 CBV源码分析

# 基于类的视图---》讲过了
-必须要继承它:from django.views import View
 
# drf的东西,都是写cbv,必须要继承View


#######流程分析
# path('books/', views.BookViwe.as_view())
# views.BookViwe.as_view()的执行结果,是函数内存地址----》view这个函数的内存地址
# 请求来了---》路由匹配成功----》会执行 这个函数---》view(request)
# view----》self.dispatch(request)
def view(request, *args, **kwargs):
   return self.dispatch(request, *args, **kwargs)
 
# dispatch---》你是什么请求,就会执行视图类中请求名字的方法
 def dispatch(self, request, *args, **kwargs):
  # 请求方法变成小写字符串 ,如果是get请求,就是 'get'
     # self.http_method_names 列表 ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
     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:
           handler = self.http_method_not_allowed
       # 执行get方法---》视图函数的get方法
       return handler(request, *args, **kwargs)




######### 你是什么请求,就会执行视图类中请求名字的方法

 

2 APIView的基本使用

# 上一节分析了---》View的执行流程
# 如果使用了drf,以后写的都是cbv,但是都是继承drf提供的视图类,APIView
from rest_framework.views import APIView
# 以后写的cbv要继承 APIView 及其子类
########## drf是个app,需要注册 ##########
INSTALLED_APPS = [
...
   'rest_framework'   # 一定不要忘了注册
]

# 2个坑: app后不加逗号,使用三引号加注释


### 补充: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', # 静态资源
   'app01.apps.App01Config',
   'rest_framework',   # 一定不要忘了注册
 
]

 

class BookViwe(APIView):
   def get(self,request):
       # return HttpResponse('hello web') # 以后不要用django原生的响应了:四件套:render,HttpResponse,Redirect,JsonResponse
       return Response('hello web') # drf提供的响应--》放字符串,字典,列表:HttpResponse+JsonResponse结合体


# 由于继承了APIView---》执行APIView的as_view---》执行APIView的dispatch---》内部执行变化了

 

3 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 包装了响应对象

 

4 Request对象源码分析

# 以后视图类中使用的request对象,是rest_framework.request.Request的对象
# 源码
class Request:
#1 把老的request放到了新的request的_request属性了
   # 新的request--》request._request 是老的
-__init__:    self._request = request(这个request是老的)
     
   # 2 以后新的request用起来跟原来一样用
  # 取出原来老request的属性,以下方法取,麻烦
    request._request.POST
       request._request.GET
       request._request.method
       # 重写了__getattr__ 魔法方法,. 拦截 --》对象.属性如果属性不存在,触发这个方法执行
       # 新的request.POST,新的request中没有POST,触发Request类的__getattr__
       def __getattr__(self, attr):
         try:
          # 通过反射,去拿老request的属性或方法
             return getattr(self._request, attr)
         except AttributeError:
             return self.__getattribute__(attr)
 
# 3 新的request有个data方法,包装成了数据属性
  -前端无论什么编码方式传得body体中的数据,都从request.data中取,当字典用即可
    -原生djagno,如果是formdata,urlencoded是从POST中取,如果是json,从body中取出来自己转
       
   # 4 新的request有个query_params方法,包装成了数据属性
    -就是原来老的request的GET属性
     
   # 5 上传文件,跟之前一样用,但是人家重写了
   
   
   
   
# 新的request重点
-1 老的request是新的request._request
-2  跟原来一样用
   -3 body提交的数据都从request.data中取
   -4 请求地址中的数据都从request.query_params中取

image-20220614111816196

 

 

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格式返回给前端

 

 

 

 

 

5.2 路由

 path('books/', views.BookAPIView.as_view()),

5.3 视图类

from .models import Book
from .serializer import BookSerializer
class BookAPIView(APIView):
   def get(self,request):
       # 取出所有图书的qs对象
       books=Book.objects.all()
       # 借助于序列化类--》写一个序列化类
       # 类实例化时:instance:要序列化的对象   many:True 多条 先记着这两个参数
       ser=BookSerializer(instance=books,many=True)
       # ser.data 完成了序列化
       print(ser.data)  # 把qs对象,转成了字典,根据序列化类中你写的字段转的
       return Response(ser.data)

 

5.3 序列化类

from rest_framework import serializers

class BookSerializer(serializers.Serializer):  # 一定要继承Serializer
   # 写要序列化的字段,比如,不想把作者给前端
   name = serializers.CharField()  # 字段类,跟models中一一对应
   price = serializers.IntegerField()  # 字段类,跟models中一一对应
   publish = serializers.CharField()  # 字段类,跟models中一一对应
   author = serializers.CharField()  # 字段类,跟models中一一对应

 

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

# 字段类和字段属性

### 字段类:跟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/qinyanghua/p/16411875.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有