首页 > 其他分享 >drf : 通用视图类和(GenericAPIView)5个视图扩展类,九个视图子类,视图集。

drf : 通用视图类和(GenericAPIView)5个视图扩展类,九个视图子类,视图集。

时间:2024-03-25 11:34:29浏览次数:27  
标签:GenericAPIView get 子类 self request 视图 class

视图

REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写。

APIView

rest_framework.views.APIView

APIViewREST framework提供的所有视图的基类,继承自Django的View父类。

GenericAPIView使用[通用视图类]

继承自APIVIew,主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixin扩展类。

点击第一层查看代码

class BookView(APIView):
    renderer_classes = [JSONRenderer]

    # 创建数据反序列化
    def post(self, request):
        ser = BookSerializers(data=request.data)
        if ser.is_valid():
            ser.save()
        return Response(ser.data)

    # 读取序列化
    def get(self, request):
        book_list = Books.objects.all()
        # many=True 代表序列化多条数据
        ser = BookSerializers(instance=book_list, many=True)

        response = {'code': 100, 'msg': '查询成功', 'result': ser.data}
        return Response(response, status=status.HTTP_202_ACCEPTED, headers={'name': 'junjie'})


# 查询单条
class BookDetailView(APIView):
    def get(self, request, pk):
        book = Books.objects.filter(pk=pk).first()
        ser = BookSerializers(instance=book)
        return Response(ser.data)

    def delete(self, request, pk):
        Books.objects.filter(pk=pk).delete()
        return Response()

    # 修改
    def put(self, request, pk):
        book = Books.objects.filter(pk=pk).first()
        ser = BookSerializers(instance=book, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)

GenericAPIView[通用视图类]的方法属性以及方法,第二层的演变。

* 属性
* serializer_class指明视图使用的序列化器
* 方法
* get_serializer_class(self)

现在来想继承GenericAPIView来写视图函数改如何写?先查看GenericAPIView类定义了什么属性和方法。

图书的五个接口,第二层,精简模型类和序列化类

from .models import Books, Publish
from rest_framework.generics import GenericAPIView
from .serizlizer import BookSerializers, PublishSerializers
from rest_framework.response import Response


class BookAPIView(GenericAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers

    def get(self, request):
        book_list = self.get_queryset()
        ser = self.get_serializer(instance=book_list, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)


class BookDetailView(GenericAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers

    def get(self, request, pk):
        book_list = self.get_object()
        ser = self.get_serializer(instance=book_list)
        return Response(ser.data)

    def put(self, request, pk):
        book_obj = self.get_object()
        # 得到序列化类对象,传入单条对象和要修改的数据字段
        ser = self.get_serializer(instance=book_obj, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)

    def delete(self, request, pk):
        book = self.get_object()
        book.delete()
        return Response()

如果想要再写一个视图类只需要继承GenericAPIView修改queryset和serializer_class即可,那么有没有别的方法可以节省代码?

使用GenericAPIView+5个视图扩展类

from rest_framework.mixins import 
CreateModelMixin, # 创建单个
ListModelMixin, # 查询所有
DestroyModelMixin, # 删除单个 碟嘶踹
UpdateModelMixin, # 新建单个
RetrieveModelMixin # 查询单个 瑞吹雾

代码如下:

from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, \
    ListModelMixin
from rest_framework.generics import GenericAPIView
from .models import Books, Publish
from .serizlizer import BookSerializers, PublishSerializers


class BookAPIView(GenericAPIView,
                  # 创建数据                  
                  CreateModelMixin,
                  # 查看所有
                  ListModelMixin):
    queryset = Books.objects.all()
    serializer_class = BookSerializers

    def get(self, request):
        print(request)
        return self.list(request)

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


class BookDetailView(GenericAPIView,
                     UpdateModelMixin,    # 修改单条数据
                     DestroyModelMixin,   # 删除单条
                     RetrieveModelMixin): # 查询单条
    queryset = Books.objects.all()
    serializer_class = BookSerializers

    def get(self, request, pk):
        print(request)
        return self.retrieve(request, pk)

    def delete(self, request, pk):
        print(request)
        return self.destroy(request, pk)

    def put(self, request, pk):
        return self.update(request, pk)


为什么叫视图扩展类:因为他不是视图类,视图类必须是继承View/APIView。

还有没有办法再精简代码?

GenericAPIView的视图子类,第三层

1)CreateAPIView

提供 post 方法

继承自: GenericAPIView、CreateModelMixin

2)ListAPIView

提供 get 方法

继承自:GenericAPIView、ListModelMixin

3)RetrieveAPIView

提供 get 方法

继承自: GenericAPIView、RetrieveModelMixin

4)DestoryAPIView

提供 delete 方法

继承自:GenericAPIView、DestoryModelMixin

5)UpdateAPIView

提供 put 和 patch 方法

继承自:GenericAPIView、UpdateModelMixin

以及:

RetrieveAPIView, ListCreateAPIView, RetrieveUpdateDestroyAPIView, RetrieveUpdateAPIView, RetrieveDestroyAPIView
from rest_framework.generics import CreateAPIView, UpdateAPIView, DestroyAPIView, ListAPIView, RetrieveAPIView, \
    ListCreateAPIView, RetrieveUpdateDestroyAPIView, RetrieveUpdateAPIView, RetrieveDestroyAPIView


class BookAPIView(ListCreateAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers


class BookDetailAPIView(RetrieveUpdateDestroyAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers

总结:

#两个基类
APIView
GenericAPIView:有关数据库操作,queryset 和serializer_class


#5个视图扩展类(rest_framework.mixins)
CreateModelMixin:create方法创建一条
DestroyModelMixin:destory方法删除一条
ListModelMixin:list方法获取所有
RetrieveModelMixin:retrieve获取一条
UpdateModelMixin:update修改一条

#9个子类视图(rest_framework.generics)
CreateAPIView:继承CreateModelMixin,GenericAPIView,有post方法,新增数据
DestroyAPIView:继承DestroyModelMixin,GenericAPIView,有delete方法,删除数据
ListAPIView:继承ListModelMixin,GenericAPIView,有get方法获取所有
UpdateAPIView:继承UpdateModelMixin,GenericAPIView,有put和patch方法,修改数据
RetrieveAPIView:继承RetrieveModelMixin,GenericAPIView,有get方法,获取一条


ListCreateAPIView:继承ListModelMixin,CreateModelMixin,GenericAPIView,有get获取所有,post方法新增
RetrieveDestroyAPIView:继承RetrieveModelMixin,DestroyModelMixin,GenericAPIView,有get方法获取一条,delete方法删除
RetrieveUpdateAPIView:继承RetrieveModelMixin,UpdateModelMixin,GenericAPIView,有get获取一条,put,patch修改
RetrieveUpdateDestroyAPIView:继承RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView,有get获取一条,put,patch修改,delete删除

第五层,直接写五个接口最终演示,自动生成路由。

from rest_framework.viewsets import ModelViewSet

# ModelViewSet继承了5个视图扩展类,GenericViewSet 和 ViewSetMixin
class BookAPIView(ModelViewSet):
    queryset = Books.objects.all()
    serializer_class = BookSerializers

继承五个视图扩展类的作用为用了五个接口方法。

GenericViewSet是什么?

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    """
    The GenericViewSet class does not provide any actions by default,
    but does include the base set of generic view behavior, such as
    the `get_object` and `get_queryset` methods.
    """
    pass
  
  
"""
已知:generics.GenericAPIView 中有View和APIView,以及四个方法
    def get_queryset(self):
       
    def get_object(self):
      
    def get_serializer(self, *args, **kwargs):
    
    def get_serializer_class(self):
"""

ViewSetMixin

class ViewSetMixin:

    @classonlymethod
    def as_view(cls, actions=None, **initkwargs):

        cls.name = None
        cls.description = None

        cls.suffix = None

        cls.detail = None

        cls.basename = None

        # 注释:
				"""
				此处与url相对应,actions是什么?
				path('books/', views.BookAPIView.as_view({'get':'list','post':'create'})),
				actions = {'get':'list','post':'create'}
				如果没有写则报异常。
				"""
        if not actions:
            raise TypeError("The `actions` argument must be provided when "
                            "calling `.as_view()` on a ViewSet. For example "
                            "`.as_view({'get': 'list'})`")
            # 注释:
  	    """
  	    字典.items()是将K,V拆出,此时method=K,action=V
            以{'get':'list','post':'create'}举例。
  	    get = method,list = action
  	    """
            for method, action in actions.items():
              	# 注释:
                """
                此时的self为视图类对象BookAPIView
                action是上述所讲的url,as_view的第一个参数。
                
                getattr反射,此时视图类对象中没有list,到父类ModelViewSet --> 
                mixins.ListModelMixin -->  def list(self, request, *args, **kwargs):
                
                handler 便是反射出来的list
                
                setattr设置值,将list映射成get,视图中的get方法实质上是list方法。
                客户端发送get请求就能找到list
                这里主要用作区分用户是查询单条还是查询所有
                """
                handler = getattr(self, action)
                setattr(self, method, handler)

            self.request = request
            self.args = args
            self.kwargs = kwargs

            # And continue as usual
            return self.dispatch(request, *args, **kwargs)

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())

        # We need to set these on the view function, so that breadcrumb
        # generation can pick out these bits of information from a
        # resolved URL.
        view.cls = cls
        view.initkwargs = initkwargs
        view.actions = actions
        return csrf_exempt(view)

第五层

导入模块

from rest_framework.viewsets import ModelViewSet

直接写五个接口最终演示,自动生成路由。

from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet, GenericViewSet, ViewSet


# 直接写五个接口,一定要继承(ViewSetMixin),才能自动生成路由

# class BookAPIView(ModelViewSet):
#     queryset = Books.objects.all()
#     serializer_class = BookSerializers

# 查询所有和查询单个,如果只继承了ReadOnlyModelViewSet,路由也需要更改。
# class BookAPIView(ReadOnlyModelViewSet):
#     queryset = Books.objects.all()
#     serializer_class = BookSerializers


# GenericViewSet:继承了(ViewSetMixin, generics.GenericAPIView)

# ViewSet:继承了(ViewSetMixin, views.APIView)


class BookAPIView(ViewSet):
    def xjz(self, request):
        return Response("junjie")

url

# 自动生成路由
from rest_framework.routers import SimpleRouter

router = SimpleRouter()
# 必须继承(ViewSetMixin),才能自动生成路由
router.register('books', views.BookAPIView)

urlpatterns = [
    path('admin/', admin.site.urls),

    # 将请求映射到对应的方法
    path('books/', views.BookAPIView.as_view({'get':'list'})),
    path('books/<int:pk>', views.BookAPIView.as_view({'get':'retrieve'})),
]

urlpatterns += router.urls

导入模块

from rest_framework.routers import SimpleRouter
from django.urls import path,include
router = SimpleRouter()
# 必须继承(ViewSetMixin),才能自动生成路由
router.register('admin', views.BookAPIView)

urlpatterns = [
    # path('admin/', admin.site.urls),

    path('api/',include(router.urls))
]

此时浏览器访问admin的路由:http://127.0.0.1:8000/api/admin/

标签:GenericAPIView,get,子类,self,request,视图,class
From: https://www.cnblogs.com/HeroZhang/p/18094023

相关文章

  • Qt6.0开发 第五章 模型-视图结构
    第五章模型-视图结构模型-视图结构概述模型-视图结构是一种将数据存储和界面分离的编程方法.模型存储数据,视图组件显示模型中的数据,在视图组件里修改的数据会被自动保存到模型里.GUI程序的主要功能是可由用户在界面上编辑和修改数据,典型的如数据库应用程序.在数据库应用程......
  • 视图渲染数据-iframe跨越问题
    控制器传入数据视图渲染#for循环{%foriteminoverviewof%}{{item.epg}}{%endfor%}#跳转链接{%url'look'%}path('look/',views.look,name='look'),iframe跨越问题X_FRAME_OPTIONS='SAMEORIGIN'#视图控制器引用fromdjango.......
  • 事务、索引、视图、数据库备份和恢复
    事务#创建银行卡CREATEtableaccount(cidintUNIQUE,cnameVARCHAR(20),moneyDECIMAL(10,2)UNSIGNED)INSERTintoaccountVALUES(12345,'李嘉欣',1000);INSERTintoaccountVALUES(12346,'徐杰',2000);#管理手动事务的语句/*开启事务BEGIN  提交事务CO......
  • 视图
    定义:是一种虚拟表,和普通表一样使用,不包含任何实际存储的数据,而是通过执行定义的查询来动态生成数据。这是mysql5.0.1版本出现的新特性,通过表动态生成 在数据库中,视图(View)是基于查询结果的虚拟表,它是一个具有字段和行的结构化数据集。视图是一个虚拟表,不包含任何实际存储的数......
  • mysql用视图union多表
    订单表xfc_orderDROPTABLEIFEXISTS`xfc_order`;CREATETABLE`xfc_order`(`order_id`int(11)unsignedNOTNULLAUTO_INCREMENT,`order_code`varchar(32)NOTNULLCOMMENT'订单号',`pay_time`int(11)unsignedNOTNULLCOMMENT'付款时间',......
  • 【测试开发学习历程】MySQL增删改操作 + 备份与还原 + 索引、视图、存储过程
    前言:SQL内容的连载,到这里就是最后一期啦!如果有小伙伴要其他内容的话,我会追加内容的。(前提是我有学过,或者能学会)接下来,我们就要开始python内容的学习了~~ 目录1 MySQL增删改操作1.1数据添加操作1.1.1插入完整的行1.1.2插入多行1.2数据更新操作1.3数据删除操......
  • 2、URL和视图的映射
    fromflaskimportFlask,requestapp=Flask(__name__)#url的组成部分:http[80]/https[443]://www.qq.com:443/path#默认的http协议使用的是80端口,https协议使用的是443端口.#当我们输入www.qq.com时,实际浏览器会处理加上443端口#url与视图:path与视图@app.route("/")d......
  • MySQL 视图、事件、函数、储存过程
    正文视图https://blog.csdn.net/moxigandashu/article/details/63254901事件(类似定时任务)https://zhuanlan.zhihu.com/p/450454992函数https://www.cnblogs.com/zhangminghui/p/4113160.html储存过程(处理复杂逻辑)https://blog.csdn.net/whf_a/article/details/114871866......
  • 【11.0】Django框架之视图层
    【一】三板斧【1】HttpResponseHttpResponse是Django中用于创建HTTP响应对象的类,它允许你构建并返回服务器对客户端请求的数据和状态。当需要直接返回纯文本数据(如JSON格式的数据)或者HTML页面时,可以使用HttpResponse。fromdjango.httpimportHttpResponsedef......
  • mysql 存储过程 视图 理解参考
    存储过程(StoredProcedure): 存储过程是一组预编译的SQL语句和控制结构的集合,类似于程序中的子例程或函数。存储过程可以接受参数,并且可以在执行过程中进行条件判断、循环和其他逻辑控制。存储过程通常用于封装和重用复杂的数据库操作,可以执行一系列的SQL语句,进行数据处理、业......