Rest_Framework由浅入深:从CBV到ModelViewSet源码一步步解析

这篇具有很好参考价值的文章主要介绍了Rest_Framework由浅入深:从CBV到ModelViewSet源码一步步解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Rest_Framework由浅入深:从CBV到ModelViewSet源码一步步解析

1、Django Rest_Framework介绍

Django REST framework是一个建立在Django基础之上的Web应用开发框架,可以快速的开发REST API接口应用。在REST framework中,提供了序列化器Serialzier的定义,可以帮助我们简化序列化与反序列化的过程,不仅如此,还提供丰富的类视图、扩展类、视图集来简化视图的编写工作。REST framework还提供了认证、权限、限流、过滤、分页、接口文档等功能支持。REST framework提供了一个APIWeb可视化界面来方便查看测试接口。

2、特点

a、提供了定义序列化器Serializer的方法,可以快速根据 Django ORM或者其它库自动序列化、反序列化;
b、提供了丰富的类视图、Mixin扩展类,简化视图的编写,丰富的定制层级:函数视图、类视图、视图集合到自动生成 API
c、满足各种需要多种身份认证和权限认证方式的支持内置了限流系统直观的 API web 界面,可以方便我们调试开发api接口,可扩展性强,插件丰富。

一、Django的CBV

1、执行顺序:

先从路由的as_view() 开始,
执行BookView类继承的View类里的as_view() 里的view(),
view() 的返回值是View类的dispatch()
dispatch() 进行分发执行getpostput等方法。

views.py

# author xsy

from django.views import View

class BookView(View):

    def get(self,request):
        return HttpResponse('get')
    def post(self,request):
        return HttpResponse('post')

urls.py

# author xsy

from django.urls import path
from .views import *
urlpatterns = [
    path('book/', BookView.as_view()),
]

View类的大概逻辑

# author xsy

class View():

    def as_view(cls, **initkwargs):
        def view(self):
            return self.dispatch()
        return view
    
    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 )
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)

二、DRF的APIView

1、相比原生django的优势:

a、django原生的request.POST存在只会解析uriencoded 不会解析json的问题;
b、APIView类的dispatch方法解决该问题,而且还会对请求的客户端进行身份认证、权限检查、流量控制。

2、执行顺序:

先从路由的as_view() 开始,
执行BookView类继承的APIView类里的as_view()
而该as_view() 在内部重写了APIView类的父类Viewas_view() 方法,
所以执行的是父类Viewas_view()
Viewas_view()方法在内部的返回值是dispatch()
dispatch()是先从APIView类里查找,
因为APIView类有dispatch()
所以最终执行的是APIView类的dispatch() 进行分发。

views.py

# author xsy

from rest_framework.views import APIView

class BookView(APIView):

    def get(self,request):
        return HttpResponse('get')
    def post(self,request):
        return HttpResponse('post')

APIView类的大概逻辑

# author xsy

# APIView的父类View的逻辑
class View():

    def as_view(cls, **initkwargs):
        def view(self):
            return self.dispatch()
        return view
    
    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 )
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)
        
class APIView(View):
    def as_view(cls, **initkwargs):
        view = super().as_view(**initkwargs)
        return csrf_exempt(view)

    def dispatch(self, request, *args, **kwargs):
        # 构建新的request对象
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        # 初始化:认证、权限、限流组件三件套

        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
        return handler(request, *args, **kwargs)

三、序列化器

1、使用Serializer和APIView

Serializer进行序列化和反序列化
数据库的数据到前端进行序列化
前端的数据上传到数据库进行反序列化

a、**serializer.save()**的逻辑:

如果self.instance is not None执行update()
否则执行create() 分别对应put()post()
BaseSerializer类里的create()update()必须重写
所以
Bookserializers
类里有这两个方法

b、serializer.data

BookView类get()返回的serializer.data,是Serializer类data()
该方法重写了Serializer类的父类BaseSerializer类的data()方法
model.py

# author xsy

from django.db import models

# Create your models here.

class Books(models.Model):
    title = models.CharField(max_length=32,verbose_name="书籍名称")
    price = models.IntegerField(verbose_name="价格")

serializers.py

# author xsy

from rest_framework import serializers
from .models import *
class Bookserializers(serializers.Serializer):
    title = serializers.CharField(max_length=16)
    price = serializers.IntegerField()
    # 使用下面这种可以修改名称
    # jiaqian = serializers.IntegerField(source='price')

    def create(self, validated_data):
        newbook = Books.objects.create(**self.validated_data)
        return newbook
    def update(self, instance, validated_data):
        Books.objects.filter(pk=instance.pk).update(**self.validated_data)
        update_book = Books.objects.get(pk=instance.pk)
        return update_book

views.py

# author xsy

from rest_framework.views import APIView
# 不使用djangO自带的HttpResponse  而是用rest_framework的Response可以将返回值变成json
from rest_framework.response import Response
from .models import *
from .serializers import *

class BookView(APIView):
    def get(self,request):
        books = Books.objects.all()
        serializer = Bookserializers(instance=books,many=True)
        return Response(serializer.data)
    def post(self,request):
        serializer = Bookserializers(data=request.data)
        if serializer.is_valid():
            # Books.objects.create(**serializer.validated_data)
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)

class BookDetailView(APIView):
    def get(self,request,id):
        book = Books.objects.get(pk=id)
        serializer = Bookserializers(instance=book,many=False)
        return Response(serializer.data)
    def put(self,request,id):
        serializer = Bookserializers(instance=Books.objects.get(pk=id),data=request.data)
        if serializer.is_valid():
            # Books.objects.filter(pk=id).update(**serializer.validated_data)
            # serializer.instance = Books.objects.get(pk=id)
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)
    def delete(self,request,id):
        Books.objects.get(pk=id).delete()
        return Response()

urls.py

# author xsy

from django.urls import path,re_path
from .views import *
urlpatterns = [
    path('books/', BookView.as_view()),
    re_path('book/(\d+)', BookDetailView.as_view()),
]

2、ModelSerializer和GenericAPIView

a、ModelSerializer相比Serializer

已经将模型的字段在内部进行封装;
在内部已经重写create()update()

b、GenericAPIView相当于进一步封装APIView

1、GenericAPIView继承APIView类,self.get_serializer_class()等于Bookserializers
2、而self.get_serializer等于self.get_serializer_class()
3、self.get_queryset() 等于取出多条数据
4、self.get_object() 等于取出一条数据
model.py

# author xsy

from django.db import models

# Create your models here.

class Books(models.Model):
    title = models.CharField(max_length=32,verbose_name="书籍名称")
    price = models.IntegerField(verbose_name="价格")

serializers.py

# author xsy

class Bookserializers(serializers.ModelSerializer):

    class Meta:
        model = Books
        # fields = '__all__'
        fields = ['title','price']

views.py

# author xsy

from rest_framework.generics import GenericAPIView
from rest_framework.response import Response

class BookView(GenericAPIView):
    queryset = Books.objects.all()
    serializer_class = Bookserializers
    def get(self, request):
        books = Books.objects.all()
        # serializer = Bookserializers(instance=self.get_queryset(),many=True)
        # self.get_serializer_class()等于Bookserializers
        # self.get_serializer_class()(instance=self.get_queryset(),many=True)
        serializer = self.get_serializer(instance=self.get_queryset(),many=True)
        return Response(serializer.data)
    def post(self,request):
        # serializer = Bookserializers(data=request.data)
        # serializer = self.get_serializer_class()(data=request.data)
        # 三行作用相同
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            # Books.objects.create(**serializer.validated_data)
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)

class BookDetailView(GenericAPIView):
    queryset = Books.objects.all()
    serializer_class = Bookserializers
    def get(self,request,pk):
        # book = Books.objects.get(pk=id)
        # serializer = Bookserializers(instance=book,many=False)
        serializer = self.get_serializer(instance=self.get_object(),many=False)
        return Response(serializer.data)
    def put(self,request,pk):
        # serializer = Bookserializers(instance=Books.objects.get(pk=id),data=request.data)
        serializer = self.get_serializer(instance=self.get_object(),data=request.data)
        if serializer.is_valid():
            # Books.objects.filter(pk=id).update(**serializer.validated_data)
            # serializer.instance = Books.objects.get(pk=id)
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)
    def delete(self,request,pk):
        # Books.objects.get(pk=id).delete()
        self.get_object().delete()
        return Response()

四、视图

1、mixins

ListModelMixinlist方法对应BookViewget方法
CreateModelMixincreate方法对应BookViewpost方法
RetrieveModelMixinretrieve方法对应BookDetailViewget方法
UpdateModelMixinupdate方法对应BookDetailViewput方法
DestroyModelMixindestroy方法对应BookDetailViewdelete方法
views.py

# author xsy

# #  #################### mixins  ################################

from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin

class BookView(ListModelMixin,CreateModelMixin,GenericAPIView):
    queryset = Books.objects.all()
    serializer_class = Bookserializers

    def get(self,request):
        return self.list(request)
    def post(self,request):
        return self.create(request)

class BookDetailView(RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView):
    queryset = Books.objects.all()
    serializer_class = Bookserializers

    def get(self,request,pk):
        return self.retrieve(request,pk)
    def put(self,request,pk):
        return self.update(request,pk)
    def delete(self,request,pk):
        return self.destroy(request,pk)

2、mixins再封装版

ListCreateAPIView类将list方法封装到get方法里,将create方法封装到post方法里
RetrieveUpdateDestroyAPIView类将retrieve封装到get方法里,将update方法封装到put方法里,将destroy方法封装到delete方法里
views.py

# author xsy

# #  #################### mixins再封装  #########################################

from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView
class BookView(ListCreateAPIView):
    queryset = Books.objects.all()
    serializer_class = Bookserializers

class BookDetailView(RetrieveUpdateDestroyAPIView):
    queryset = Books.objects.all()
    serializer_class = Bookserializers

五、视图的再次精简化:GenericViewSet和ModelViewSet

1、GenericViewSet

BookView类继承六个类,其中GenericViewSet类继承的ViewSetMixin类实现了将路由传的字典映射到对应的方法,这样才可以将BookViewBookDetailView和成一个类,而继承的其他五个类对应了增删改查方法
views.py

# author xsy

#  #################### 四、GenericViewSet  #########################################

from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin

class BookView(GenericViewSet,ListModelMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin):
    queryset = Books.objects.all()
    serializer_class = Bookserializers

urls.py

# author xsy

urlpatterns = [
    # GenericViewSet
    path('books/', BookView.as_view({'get':'list','post':'create'})),
    re_path('book/(?P<pk>\d+)', BookView.as_view({'get':'retrieve','delete':'destroy','put':'update'})),
    ]

2、ModelViewSet

ModelViewSet类继承了CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin,ListModelMixin,
GenericViewSet这六个类
views.py

# author xsy

from rest_framework.viewsets import ModelViewSet

class BookView(ModelViewSet):
    queryset = Books.objects.all()
    serializer_class = Bookserializers

urls.py文章来源地址https://www.toymoban.com/news/detail-464343.html

# author xsy

from rest_framework import routers

router = routers.DefaultRouter()
router.register('book',BookView)
urlpatterns = [

]
urlpatterns += router.urls

到了这里,关于Rest_Framework由浅入深:从CBV到ModelViewSet源码一步步解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【个人笔记】由浅入深分析 ClickHouse

    项目中不少地方使用到ClickHouse,就对它做了一个相对深入一点的了解和研究。并对各种知识点及整理过程中的一些理解心得进行了汇总并分享出来,希望对其他同学能有帮助。 本文主要讲解ClickHouse的特点、读写过程、存储形式、索引、引擎、物化视图等特性。 适合 入门和

    2024年01月20日
    浏览(47)
  • 【由浅入深学习MySQL】之索引进阶

    本系列为:MySQL数据库详解,为千锋资深教学老师独家创作 致力于为大家讲解清晰MySQL数据库相关知识点,含有丰富的代码案例及讲解。如果感觉对大家有帮助的话,可以【关注】持续追更~ 文末有本文重点总结,技术类问题,也欢迎大家和我们沟通交流! 从今天开始本系列

    2024年02月05日
    浏览(45)
  • 手拉手Vue组件由浅入深

    组件 (Component) 是 Vue.js 最强大的功能之一,它是html、css、js等的一个聚合体,封装性和隔离性非常强。 组件化开发:     1、将一个具备完整功能的项目的一部分分割多处使用     2、加快项目的进度     3、可以进行项目的复用 组件注册分为:全局注册和局部注册 目录

    2024年01月18日
    浏览(46)
  • 由浅入深介绍 Python Websocket 编程

    1.1 websocket 协议简介 Websocket协议是对http的改进,可以实现client 与 server之间的双向通信; websocket连接一旦建立就始终保持,直到client或server 中断连接,弥补了http无法保持长连接的不足,方便了客户端应用与服务器之间实时通信。 适用场景 html页面实时更新, 客户端的html页面

    2024年02月03日
    浏览(42)
  • Springboot3+EasyExcel由浅入深

    环境介绍 技术栈 springboot3+easyexcel 软件 版本 IDEA IntelliJ IDEA 2022.2.1 JDK 17 Spring Boot 3 EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。 他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。 官网https://easyexcel.opensource.ali

    2024年01月16日
    浏览(47)
  • 由浅入深理解C#中的事件

    本文较长,给大家提供了目录,可以直接看自己感兴趣的部分。 前面介绍了C#中的委托,事件的很多部分都与委托类似。实际上,事件就像是专门用于某种特殊用途的简单委托,事件包含了一个私有的委托,如下图所示: 有关事件的私有委托需要了解的重要事项如下: 1、事

    2024年02月03日
    浏览(44)
  • 【由浅入深学MySQL】- MySQL连接查询

    本系列为:MySQL数据库详解,为千锋教育资深Java教学老师独家创作 致力于为大家讲解清晰MySQL数据库相关知识点,含有丰富的代码案例及讲解。如果感觉对大家有帮助的话,可以【点个关注】持续追更~ 文末有重点总结和福利内容! 技术类问题,也欢迎大家和我们沟通交流!

    2024年02月05日
    浏览(63)
  • 什么是感知机——图文并茂,由浅入深

    生活中常常伴随着各种各样的逻辑判断,比如看到远方天空中飘来乌云,打开手机看到天气预报说1小时后40%的概率下雨,此时时候我们常常会做出等会下雨,出门带伞的判断。 上述思考过程可以抽象为一个”与“的”神经逻辑“。当”看到乌云“和”天气预报40%下雨“同时

    2023年04月20日
    浏览(41)
  • 由浅入深剖析 Apollo(阿波罗)架构

    目录 一、介绍 二、架构和模块 三、架构剖析 1.最简架构  2. 高可用保障  3.多接口扩展 四、总结 Apollo(阿波罗)是携程框架部研发并开源的一款生产级的配置中心产品,它能够集中管理应用在不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的

    2024年02月13日
    浏览(41)
  • 由浅入深了解机器学习和GPT原理

    我不是一个机器学习专家,本来是一名软件工程师,与人工智能的互动很少。我一直渴望深入了解机器学习,但一直没有找到适合自己的入门方式。这就是为什么,当谷歌在2015年11月开源TensorFlow时,我非常兴奋,知道是时候开始学习之旅了。不想过于夸张,但对我来说,这就

    2024年02月09日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包