ICode9

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

12_02、初识drf

2022-04-01 01:00:39  阅读:190  来源: 互联网

标签:02 12 APIView self request 视图 --- view drf


一、drf介绍和快速使用

1、drf介绍

1.1 drf的替代品

需要注意,原生Django框架,即使不导入drf相关模块,也可以写出符合restful的相关规范

举个例子:

# 地址:127.0.0.1:8080/books
# 路由:path('/books',views.books)
# 视图函数中:通过orm查出所有图书(qs)--->序列化(for循环自己拼成列表套字典[{name:西游记,price:99},{name:红楼梦,price:99}])---->JsonResponse返回给前端

1.2 drf介绍

Django REST framework是一个建立在Django基础之上的Web 应用开发框架,可以快速的开发REST API接口应用。

在REST framework中,提供了序列化器Serialzier的定义,可以帮助我们简化序列化与反序列化的过程,不仅如此,还提供丰富的类视图、扩展类、视图集来简化视图的编写工作。

REST framework还提供了认证、权限、限流、过滤、分页、接口文档等功能支持。

REST framework提供了一个API 的Web可视化界面来方便查看测试接口。

1.3 drf的安装和注意事项

pip3 install djangorestframework

注意:drf需要相应的python解释器和Django框架支持,否则安装过程中,会把python和Django自动更新至最新版本

Python (3.6, 3.7, 3.8, 3.9, 3.10)
Django (2.2, 3.0, 3.1, 3.2, 4.0)

2、drf快速使用

# 视图
from rest_framework.viewsets import ModelViewSet
from .models import Book # 模块导入使用相对导入
# from app01.models import Book # 使用绝对导入
from .serializer import BookSerializer
class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer


# 路由
from rest_framework.routers import SimpleRouter
from app01 import views

router = SimpleRouter()
router.register('books', views.BookView, 'books')
urlpatterns = [
    path('admin/', admin.site.urls),
]
urlpatterns += router.urls


# 序列化类
from .models import Book
from rest_framework import serializers

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'


#模型
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.DecimalField(decimal_places=2, max_digits=5)
    author = models.CharField(max_length=32)
使用drf快速创建接口
# 针对于一个表,只需要写5个接口,以后看到的所有接口都是这5个的变形

# 查询所有,get请求,http://127.0.0.1:8000/books/  {[], [], []}
# 查询一个,get请求,http://127.0.0.1:8000/books/1/  {}
# 新增一个,post请求,http://127.0.0.1:8000/books/ body中带数据
# 修改,put请求(全局)patch请求(局部),实际编码中,基本都用put,http://127.0.0.1:8000/books/1/   body体中传入修改的数据  # 删除一个,delete请求,http://127.0.0.1:8000/books/1/

例如:

登陆接口---》本质其实是查询一个
注册接口----》本质是新增一个

注意:

使用postman测试,地址要严格,斜杠有和没有是有区别的

二、cbv源码分析流程

cbv是基于类的视图函数。

cbv的路由写法

第一个是正则匹配,第二个是函数内存地址

urlpatterns = [
    url(r'^test/', views.TestView.as_view()),
]

 执行流程

# cbv路由写法:path('test/', views.TestView.as_view())---》
第二个参数是函数内存地址---》as_view()执行完,也是一个内存地址---》
闭包函数view的内存地址---》当请求来了,路由匹配成功--》
执行view(request),传入当次请求的request对象---->return self.dispatch(request, *args, **kwargs)--->View类中找dispatch---》
如果是get请求就会执行视图类中的get方法,如果是post请求,就会执行视图类的post方法
# as_view 类的绑定方法---》View类的方法--》@classonlymethod # dispatch核心代码---》getattr反射---》从当前对象(视图类的对象)---》如果是get请求--》会拿到get方法---》handler就是get方法---》handler(request)本质就是---》get(request) handler = getattr(self, request.method.lower(), self.http_method_not_allowed) return handler(request, *args, **kwargs) # 通过描述符自己写装饰器来装饰类---》完成类似于property,classmethod。。

三、drf之APIView和Requset对象分析

1、APIView的对象分析

使用drf是用来写视图类的

APIView这个类是继承的Django中View类,因为View是一个视图类,所以说APIView也是一个视图类,简单说:APIView进一步封装了view

且drf中最顶层的视图类就是APIView,所以也可以说APIView是drf中所有类的父类

# View的路径
from django.views.generic.base import View # 最真的路径
from django.views.generic import View  # 之所以能从这里导入View,因为在generic包的init里注册了
from django.views import View       # views包的init里注册了
# APIView的执行流程
路由 path('order/', views.OrderView.as_view())---》第二个参数是函数内存地址---》APIView的as_view的执行结果---》本质还是用了View类的as_view内的view闭包函数,去掉了csrf认证----》当请求来了---》触发view闭包函数执行,并且传入request--->调用了self.dispatch-->self是视图类的对象,从OrderView中找dispatch,但是找不到----》父类APIView中有---》本质执行的dispatch是APIView----》

# APIView的as_view方法
  view = super().as_view(**initkwargs) # 调用APIView的父类(View)的as_view方法
  return csrf_exempt(view) # 去掉csrf_exempt的认证,以后只要继承了APIView后,csrf就无效了,无论中间件是否注释掉

# APIView的dispatch
  def dispatch(self, request, *args, **kwargs):
          # request是新的drf提供的request,它是由老的django的request得到的
          # 通过老request,生成一个新request,drf的Request的对象
        request = self.initialize_request(request, *args, **kwargs)
        # 把新的request,放到了视图类对象中
        self.request = request
        try:
           # 执行了三大认证(认证,权限,频率)
            self.initial(request, *args, **kwargs)
            # self.http_method_names是个列表
            if request.method.lower() in self.http_method_names:
                  # 原来dispatch的核心代码
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            # 原来dispatch写的,但是request已经不是老request了,是新的
            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


      
# APIView执行流程---》
  1 包装了新的Request对象,以后视图类中的方法中传入的request对象都是新的
  2 在进入视图函数之前,执行了三大认证
  3 无论三大认证还是视图函数的方法,执行过程中出了异常,都会被处理掉
      
    
    
    
    
    
#  如何包装的新的request
request = self.initialize_request(request, *args, **kwargs)---》APIView的initialize_request---》核心代码
from rest_framework.request import Request
return Request(
            request,  # 老的request
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
新的Request中:self._request = request---》新的request._request是老的request

新的:<class 'rest_framework.request.Request'>
老的:<class 'django.core.handlers.wsgi.WSGIRequest'>

# 三大认证人如何走的
self.initial(request, *args, **kwargs)---》APIView的
核心代码:
   self.perform_authentication(request)  # 认证
   self.check_permissions(request)   #权限
   self.check_throttles(request) # 频率





      
# crsf的局部禁用--》在视图函数上加装饰器---》csrf_exempt装饰器---》装饰器本质就是一个函数
@csrf_exempt       # 装饰器的@ 是一个语法糖(特殊语法)-->把下面的函数当参数传入装饰器中并且把返回结果赋值给函数名:index=csrf_exempt(index)
def index(request)
    pass
跟 csrf_exempt(index) 一毛一样
APIView的流程分析

2、Request的对象分析

# rest_framework.request.Request ---》常用属性和方法
request.data  # 前端post请求传入的数据---》在老的request.POST-->老的只能处理urlencoded和formdata编码格式,json格式不能处理---》无论前端用什么编码post提交的数据,都从data中获取
request.files # 上传的文件对象

以后直接使用新的request.method  request.path 拿到的就是老的request.method...
对象.调用属性或方法会触发 魔法方法 __getattr__
原因在于新的request类重写了__getattr__,以后新的request.method用的时候本质就是request._request.method
  def __getattr__(self, attr):
       try:
            return getattr(self._request, attr)  # 通过反射去老的里面取
        except AttributeError:
            return self.__getattribute__(attr)

          
# 总结:新的request当老的用即可,只是多了个data前端post请求传入的数据,三种编码格式都可以

 

 

标签:02,12,APIView,self,request,视图,---,view,drf
来源: https://www.cnblogs.com/erfeier/p/16079360.html

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

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

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

ICode9版权所有