RestFramework之视图组件
一、视图组件的使用
在我们自己书写视图类时需要不断书写重复冗余的代码,看起来十分繁琐不简洁易见,当然rest_framework中的视图组件帮我们做到了一些必要的步骤,使我们节省了编写冗余代码的时间。
1.视图组件的导入
from rest_framework import generics # generics.GenericAPIView 里面封装了APIView
from rest_framework.mixins import (
ListModelMixin, # ListModelMixin表示get请求,获取全部数据
CreateModelMixin, # CreateModelMixin表示post请求,添加数据
DestroyModelMixin, # DestroyModelMixin表示delete请求,删除数据
UpdateModelMixin, # UpdataModelMixin表示put请求,修改数据
RetrieveModelMixin # RetrieveModelMixin表示get请求,获取单条数据
)
2.视图组件的使用
# 视图组件优化第一版
class BookListView(ListModelMixin, CreateModelMixin, generics.GenericAPIView):
'''
使用组件的步骤:
1.获取queryset对象
2.绑定序列化类
'''
queryset = Book.objects.all()
serializer_class = BookSerializer def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs) class BookFilterView(RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin, generics.GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer def get(self, request, *args, **kwargs):
# print(self.kwargs) {'pk': '1'}
return self.retrieve(request, *args, **kwargs) def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs) def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
是不是觉得视图组件帮我们做到了很多麻烦的事,还没完下面是改进版,
# 第二版本
class BookView(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer class BookFilterView(generics.RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
不用我们自己写每个请求的方法了,去看看源码:其实是源码帮我们写了 我们要写的了。
class ListCreateAPIView(mixins.ListModelMixin,
mixins.CreateModelMixin,
GenericAPIView):
"""
Concrete view for listing a queryset or creating a model instance.
"""
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs) class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
GenericAPIView):
"""
Concrete view for retrieving, updating a model instance.
"""
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs) def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs) def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
但是,我们还是要写两个这个:
queryset = Book.objects.all()
serializer_class = BookSerializer
最终版本:

在使用时需要注意url中需要对每个请求类型声明
url:
re_path(r'book/$', views.BookView.as_view({
'get': 'list',
'post': 'create'
})),
re_path(r'book/(?P<pk>\d+)/$', views.BookView.as_view({
'get': 'retrieve',
'put': 'update',
'delete': 'destroy'
}))
# 注:在使用ModelViewSet时需要在as_view()中声明请求对应的视图方法,如:get请求对应list ( ListModelMixin )
]
导入与使用:
from rest_framework.viewsets import ModelViewSet #ModelViewSet 里面既封装了mixins又封装了generics中的方法
# 终极版
class BookView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
只需要导入ModelViewSet就可以解决我们麻烦的冗余代码,看看源码怎么帮我们解决的:
第一步: ModelViewSet类, 继承了放有具体执行每种操作的类(list, create, update, destroy, retrieve)
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
"""
pass
第二步: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
第三步: ViewSetMixin
class ViewSetMixin(object):
"""
This is the magic. Overrides `.as_view()` so that it takes an `actions` keyword that performs
the binding of HTTP methods to actions on the Resource. For example, to create a concrete view binding the 'GET' and 'POST' methods
to the 'list' and 'create' actions... view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
""" @classonlymethod
def as_view(cls, actions=None, **initkwargs):
"""
Because of the way class based views create a closure around the
instantiated view, we need to totally reimplement `.as_view`,
and slightly modify the view function that is created and returned.
"""
# The suffix initkwarg is reserved for displaying the viewset type.
# eg. 'List' or 'Instance'.
cls.suffix = None # The detail initkwarg is reserved for introspecting the viewset type.
cls.detail = None # Setting a basename allows a view to reverse its action urls. This
# value is provided by the router through the initkwargs.
cls.basename = None # actions must not be empty
if not actions:
raise TypeError("The `actions` argument must be provided when "
"calling `.as_view()` on a ViewSet. For example "
"`.as_view({'get': 'list'})`") # sanitize keyword arguments
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r" % (
cls.__name__, key)) def view(request, *args, **kwargs):
self = cls(**initkwargs)
# We also store the mapping of request methods to actions,
# so that we can later set the action attribute.
# eg. `self.action = 'list'` on an incoming GET request.
self.action_map = actions # Bind methods to actions
# This is the bit that's different to a standard view
for method, action in actions.items(): # actions ---> {"get": "list", "post": "create"} {"put": "update", "delete": "destroy", "get": "retrieve"}
handler = getattr(self, action) # 第一种get请求 self.list = getattr(self, list) 第二种 get请求 self.retrieve = getattr(self, retrieve)
setattr(self, method, handler) # 第一种get请求 self.get = self.list 第二种get请求 self.get = self.retrieve if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get 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.suffix = initkwargs.get('suffix', None)
view.actions = actions
return csrf_exempt(view)
这个类里面有as_view(cls, actions=None, **initkwargs)方法, 也就是我们的url里面写的as_view({"get": "list", "post": "create"}),执行的是这个类中的as_view()方法,而不是APIView种的as_view()方法了!
把那个参数字典传给actions,在放回的view函数中,把每种请求要执行的那种方法 setattr()设置了(看代码中注释);
然后当用户来访问时,执行那个view函数,正常执行dispatch()方法,根据请求方式分发到每种请求的方法中,这次这个方法,是使用setattr()方法设置给self的,没有具体写,也就能正常执行每种方法了。
RestFramework之视图组件的更多相关文章
- RestFramework之权限组件
一.权限组件的使用 1.首先需要导入包 from rest_framework.permissions import BasePermission 2.编写权限类 class VipPermissio ...
- RestFramework之序列化组件
一.restframework的序列化组件的使用 1.导入序列化组件与模型类 from rest_framework import serializers from app01.models impo ...
- ASP.NET Core 中文文档 第四章 MVC(3.9)视图组件
作者: Rick Anderson 翻译: 娄宇(Lyrics) 校对: 高嵩 章节: 介绍视图组件 创建视图组件 调用视图组件 演练:创建一个简单的视图组件 附加的资源 查看或下载示例代码 介绍视图 ...
- asp.net core视图组件(ViewComponent)简单使用
一.组成: 一个视图组件包括两个部分,派生自ViewComponent的类及其返回结果.类似控制器. 定义一个视图组件,如控制器一样,必须是公开,非嵌套,非抽象的类.一般,视图组件名称为类名去掉&qu ...
- ASP.NET Core MVC之ViewComponents(视图组件)
前言 大概一个来星期未更新博客了,久违了各位,关于SQL Server性能优化会和ASP.NET Core MVC穿插来讲,如果你希望我分享哪些内容可以在评论下方提出来,我会筛选并看看技术文档来对你的 ...
- ASP.NET Core Razor 视图组件
视图组件简介 在新的ASP.NET Core MVC中,视图组件类似于局部视图,但它们更强大.视图组件不使用模型绑定,仅依赖于您在调用时提供的数据. 视图组件特性: 呈现页面响应的某一部分而不是整个响 ...
- [译]ASP.NET Core 2.0 视图组件
问题 如何在ASP.NET Core 2.0中使用视图组件? 答案 新建一个空项目,修改Startup类并添加MVC服务和中间件: public void ConfigureServices(ISer ...
- ASP.NET CORE 自定义视图组件(ViewComponent)注意事项
*红色字体为固定命名,蓝色为一般命名规则,黄色为ASP.NET CORE 默认查找文件名 概要:1.简单ViewComponent的用法 2.ViewComponent控制器返回值 3.注意事项 1 ...
- Asp.Net core 视图组件ViewComponent
视图组件 ViewComponent 最近用了一下视图组件,还挺方便的,如果遇到公共的部分,可以抽出来,写成视图组件,方便调用 先上图看一下效果:比如首页的4个画红框的地方是4个模块,有些地方可能要重 ...
随机推荐
- PAT 甲级 1146 Topological Order (25 分)(拓扑较简单,保存入度数和出度的节点即可)
1146 Topological Order (25 分) This is a problem given in the Graduate Entrance Exam in 2018: Which ...
- snmp oid 和厂商对应关系
<node oid="default" name="Unknown" type="workstation"/><node ...
- Java extract amplitude array from recorded wave
转载自:http://ganeshtiwaridotcomdotnp.blogspot.com/2011/12/java-extract-amplitude-array-from.html Extra ...
- 【JS新手教程】JS中的split()方法,拆分字符串
该方法具体如代码和图中的注释,直接在语句后面加注释了.格式:要拆分的字符串.split(拆分依据的字符)例如该文中的例子,拆分人名,电话,地址.该文中用了个文本框,文本框中需要输入的格式是:人名,电话 ...
- vue react 路由history模式刷新404问题解决方案
vue单页因微信分享和自动登录需要,对于URL中存在’#’的地址,处理起来比较坑.用history模式就不会存在这样的问题.但是换成history模式,就会有个新的问题,就是页面刷新后,页面就无法显示 ...
- 最简单的策略模式代替if-else实战
一.需求 根据用户vip等级来返回不同的价格,vip等级是不固定的,随时可能要增加,价格也不是固定的. 二.常规的写法 /** * 如果有新增类型,就需要频繁的修改此处的代码! * 不符合开闭原则! ...
- 热力图heatmap使用
参考:https://www.cnblogs.com/julinhuitianxia/p/7755246.html 1.首先到echarts官网下载应用实例:http://echarts.baidu. ...
- hdoj4099(字典树+高精度)
题目链接:https://vjudge.net/problem/HDU-4099 题意:给T组询问,每个询问为一个字符串(长度<=40),求以该字符串为开始的fibonacci数列的第一个元素的 ...
- python安装OpenCV – 4.1.0
(python3) [jiangshan@localhost ~]$ pip install opencv_python==4.1.0Collecting opencv_python==4.1.0 E ...
- Quartz.Net—IJob特性
IJob默认情况下是无状态的,和其他系统没有关系 特别是job里面的jobdata每次都是新的.可以无限扩展. PersistJobDataAfterExecution JobData持久化 Job ...