rest_framework框架实现之(视图,路由,渲染器)
一视图
一 在前面我们使用视图时继承的时APIview
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
class PageView(APIView):
def get(self,request,*args,**kwargs):
#获取所有数据
roles=models.Role.objects.all().order_by('id')
#创建分页对象
pg=PageNumberPagination()
#在数据库中获取分页的数据
page_roles=pg.paginate_queryset(queryset=roles,request=request,view=self)
#对数据进行序列化
ser = PagerSerialiser(instance=page_roles, many=True)
# return Response(ser.data)
return pg.get_paginated_response(ser.data)
二 我们可以使用 GenericAPIView ,这个类同时也继承了APIview
#urls
url(r'^(?P<version>[v1|v2]+)/myview/$', views.MyviewView.as_view()), #views
class MyviewView(GenericAPIView):
queryset=models.Role.objects.all()
serializer_class = PagerSerialiser
pagination_class = PageNumberPagination
def get(self,request,*args,**kwargs):
#获取数据
roles=self.get_queryset()
#数据的分页
pager_roles=self.paginate_queryset(roles)
#数据的序列化
ser=self.get_serializer(instance=pager_roles,many=True) return Response(ser.data)
我们来看看它的源码,顺便分析一下
class GenericAPIView(views.APIView):
"""
Base class for all other generic views.
"""
# You'll need to either set these attributes,
# or override `get_queryset()`/`get_serializer_class()`.
# If you are overriding a view method, it is important that you call
# `get_queryset()` instead of accessing the `queryset` property directly,
# as `queryset` will get evaluated only once, and those results are cached
# for all subsequent requests.
queryset = None
serializer_class = None # If you want to use object lookups other than pk, set 'lookup_field'.
# For more complex lookup requirements override `get_object()`.
lookup_field = 'pk'
lookup_url_kwarg = None # The filter backend classes to use for queryset filtering
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS # The style to use for queryset pagination.
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS def get_queryset(self):
"""
Get the list of items for this view.
This must be an iterable, and may be a queryset.
Defaults to using `self.queryset`. This method should always be used rather than accessing `self.queryset`
directly, as `self.queryset` gets evaluated only once, and those results
are cached for all subsequent requests. You may want to override this if you need to provide different
querysets depending on the incoming request. (Eg. return a list of items that is specific to the user)
"""
assert self.queryset is not None, (
"'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method."
% self.__class__.__name__
) queryset = self.queryset
if isinstance(queryset, QuerySet):
# Ensure queryset is re-evaluated on each request.
queryset = queryset.all()
return queryset def get_object(self):
"""
Returns the object the view is displaying. You may want to override this if you need to provide non-standard
queryset lookups. Eg if objects are referenced using multiple
keyword arguments in the url conf.
"""
queryset = self.filter_queryset(self.get_queryset()) # Perform the lookup filtering.
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field assert lookup_url_kwarg in self.kwargs, (
'Expected view %s to be called with a URL keyword argument '
'named "%s". Fix your URL conf, or set the `.lookup_field` '
'attribute on the view correctly.' %
(self.__class__.__name__, lookup_url_kwarg)
) filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
obj = get_object_or_404(queryset, **filter_kwargs) # May raise a permission denied
self.check_object_permissions(self.request, obj) return obj def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
"""
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs) def get_serializer_class(self):
"""
Return the class to use for the serializer.
Defaults to using `self.serializer_class`. You may want to override this if you need to provide different
serializations depending on the incoming request. (Eg. admins get full serialization, others get basic serialization)
"""
assert self.serializer_class is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method."
% self.__class__.__name__
) return self.serializer_class def get_serializer_context(self):
"""
Extra context provided to the serializer class.
"""
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
} def filter_queryset(self, queryset):
"""
Given a queryset, filter it with whichever filter backend is in use. You are unlikely to want to override this method, although you may need
to call it either from a list view, or from a custom `get_object`
method if you want to apply the configured filtering backend to the
default queryset.
"""
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset @property
def paginator(self):
"""
The paginator instance associated with the view, or `None`.
"""
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator def paginate_queryset(self, queryset):
"""
Return a single page of results, or `None` if pagination is disabled.
"""
if self.paginator is None:
return None
return self.paginator.paginate_queryset(queryset, self.request, view=self) def get_paginated_response(self, data):
"""
Return a paginated style `Response` object for the given output data.
"""
assert self.paginator is not None
return self.paginator.get_paginated_response(data)
GenericAPIview
通过源码分析,我们得出的结论:
queryset = None
serializer_class = None
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
queryset和serializer默认为None
pagination_class默认为全局配置,它结果还是会在self里面找
get_queryset调用 queryset
paginate_queryset调用paginator,而paginator调用 pagination_class
get_serializer调用 serializer_class
三 使用GenericViewSet,它继承了ViewSetMixin, generics.GenericAPIView,使用的urls里面需要传参
#urls
url(r'^(?P<version>[v1|v2]+)/myview/$', views.MyviewView.as_view({'get':'list'})), #这里多了一个方法的对应关系 #views
from api.utils.serializers.page import PagerSerialiser
from rest_framework.viewsets import GenericViewSet
from rest_framework.pagination import PageNumberPagination
class MyviewView(GenericViewSet):
queryset=models.Role.objects.all()
serializer_class = PagerSerialiser
pagination_class = PageNumberPagination
def list(self,request,*args,**kwargs): #写出对应的方法
roles=self.get_queryset() pager_roles=self.paginate_queryset(roles) ser=self.get_serializer(instance=pager_roles,many=True) return Response(ser.data)
其他有一个类已经将下面的list方法写好了:ListModelMixin ,所以可以改写成
#urls
url(r'^(?P<version>[v1|v2]+)/myview/$', views.MyviewView.as_view({'get':'list'})), #这里多了一个方法的对应关系 #views
from api.utils.serializers.page import PagerSerialiser
from rest_framework.viewsets import GenericViewSet
from rest_framework.pagination import PageNumberPagination
from rest_framework.mixins import ListModelMixin #ListModelMixin 里面有list方法
class MyviewView(ListModelMixin,GenericViewSet):
queryset=models.Role.objects.all()
serializer_class = PagerSerialiser
pagination_class = PageNumberPagination
既然 list(我们理解为查)已经写好了,那么增、删、改是不是也可以这样
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
有没有集合这些方法的类呢---》有
四 ModelViewSet
ModelViewSet,它继承了六个类
'''
ModelViewSet继承了许多类
class ModelViewSet(mixins.CreateModelMixin, #创建
mixins.RetrieveModelMixin, #获取单条数据
mixins.UpdateModelMixin, #更新
mixins.DestroyModelMixin, #删除
mixins.ListModelMixin, #查看
GenericViewSet):
'''
对于增、删、改以及查单条数据,在urls里面必须有id
#urls
url(r'^(?P<version>[v1|v2]+)/myview/(?P<pk>\d+)/$', views.MyviewView.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),
#views
from api.utils.serializers.page import PagerSerialiser
from rest_framework.pagination import PageNumberPagination
from rest_framework.viewsets import ModelViewSet
class MyviewView(ModelViewSet):
queryset = models.Role.objects.all()
serializer_class = PagerSerialiser
pagination_class = PageNumberPagination
总结:
ModelViewSet继承了增删改查的类以及GenericViewSet,因此,我们写的时候将更加方便
缺点:当url里面出现查询所有数据和单条数据的时候,你就需要自己做个判断了
问题:如何能够完美的区别增删改查(单个或所有)我们可以在路由上做文章
二路由
根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件。
from django.conf.urls import url,include
from api import views
from rest_framework import routers router=routers.DefaultRouter()
router.register(r'luyou',views.MyviewView)
router.register(r'rt',views.MyviewView) urlpatterns=[
url(r'^(?P<version>[v1|v2]+)/',include(router.urls)),
] #views
class MyviewView(ModelViewSet):
queryset = models.Role.objects.all()
serializer_class = PagerSerialiser
pagination_class = PageNumberPagination
它会将上面的路由转化:
^api/ ^(?P<version>[v1|v2]+)/ ^luyou/$ [name='role-list'] ---》http://127.0.0.1:8000/api/v1/luyou/
^api/ ^(?P<version>[v1|v2]+)/ ^luyou\.(?P<format>[a-z0-9]+)/?$ [name='role-list'] --》http://127.0.0.1:8000/api/v1/luyou.json/
^api/ ^(?P<version>[v1|v2]+)/ ^luyou/(?P<pk>[^/.]+)/$ [name='role-detail'] -->http://127.0.0.1:8000/api/v1/luyou/1/
^api/ ^(?P<version>[v1|v2]+)/ ^luyou/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='role-detail'] -->http://127.0.0.1:8000/api/v1/luyou/1.json/
^api/ ^(?P<version>[v1|v2]+)/ ^rt/$ [name='role-list'] --->http://127.0.0.1:8000/api/v1/rt/
^api/ ^(?P<version>[v1|v2]+)/ ^rt\.(?P<format>[a-z0-9]+)/?$ [name='role-list'] --->http://127.0.0.1:8000/api/v1/rt.json
^api/ ^(?P<version>[v1|v2]+)/ ^rt/(?P<pk>[^/.]+)/$ [name='role-detail'] --->http://127.0.0.1:8000/api/v1/rt/1/
^api/ ^(?P<version>[v1|v2]+)/ ^rt/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='role-detail'] -->http://127.0.0.1:8000/api/v1/rt/1.json/
^api/ ^(?P<version>[v1|v2]+)/ ^$ [name='api-root'] --->http://127.0.0.1:8000/api/v1/
^api/ ^(?P<version>[v1|v2]+)/ ^\.(?P<format>[a-z0-9]+)/?$ [name='api-root'] --->http://127.0.0.1:8000/api/v1/.json
三渲染器
根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件,它大致有下面四种
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer,AdminRenderer,HTMLFormRenderer #分别对应json格式,api格式,表格,html表单格式
class MyviewView(APIView):
renderer_classes = [AdminRenderer,BrowsableAPIRenderer]
def get(self,request,*args,**kwargs):
roles=models.Role.objects.all()
pg=MyCursorPagination()
pager_roles=pg.paginate_queryset(queryset=roles,request=request,view=self)
ser=PagerSerialiser(instance=pager_roles,many=True) return Response(ser.data)
有一点要注意:使用HTMLFormRenderer 的时候容易报错,一般不使用
'ListSerializer' object is not iterable #它只能有一个序列化对象
最后,它的全局配置
REST_FRAMEWORK = {
"DEFAULT_RENDERER_CLASSES":[
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
]
}
rest_framework框架实现之(视图,路由,渲染器)的更多相关文章
- Django-RestFrameWork之分页 视图 路由 渲染器
目录 一.分页 二.视图 三.路由 四.渲染器 一.分页 试问如果当数据量特别大的时候,你是怎么解决分页的? 方式a.记录当前访问页数的数据id 方式b.最多显示120页等 方式c.只显示上一页,下一 ...
- Django rest framework(8)---- 视图和渲染器
django rest framework 之视图 序列化器 PagerSerialiser from rest_framework import serializers from api im ...
- Django_rest_framework_渲染器/解析器/路由控制/分页
目录 渲染器 解析器 路由控制 分页 渲染器 简介 什么是渲染器 根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件. 渲染器的作用 序列化.友好的展示数据 渲染器配置 首先要在set ...
- rest_framework之渲染器
渲染器简介 什么是渲染器 根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件. 渲染器的作用 序列化.友好的展示数据 渲染器配置 首先要在settins.py中将rest_framew ...
- 29.渲染器Renderer
什么是渲染器 渲染器就是将服务器生成的数据格式转为http请求的格式 渲染器触发及参数配置 在DRF配置参数中,可用的渲染器作为一个类的列表进行定义 但与解析器不同的是,渲染器的列表是有顺 ...
- django的rest framework框架——分页、视图、路由、渲染器
一.rest framework的分页 1.使用rest framework内置类PageNumberPagination实现分类 from django.conf.urls import url f ...
- Django REST framework 之分页,视图,路由,渲染器
1.分页 2.视图 3.路由 4.渲染器 1.分页 方法一: from django.shortcuts import render from rest_framework.versioning im ...
- Django Rest Framework(分页、视图、路由、渲染器)
一.分页 试问如果当数据量特别大的时候,你是怎么解决分页的? 方式a.记录当前访问页数的数据id 方式b.最多显示120页等 方式c.只显示上一页,下一页,不让选择页码,对页码进行加密 1.基于lim ...
- DRF 的视图,路由和渲染器
DRF 的视图,路由和渲染器 1 视图 简单的增删改查 : ModelViewSet; 复杂的操作使用APIView 和 GenericViewSet APIView(View) class Home ...
随机推荐
- css3 序列帧动画抖动
页面需要一个动画,设计师给了动画的序列帧 项目由vue构建,使用css3做动画 html <div class="work_two_main"></div> ...
- PHP微信红包生成算法的程序源码(用抛物线的模型实现)
代码如下: <?php /* * 红包生成随机算法 */ header("Content-type:text/html;charset=utf-8"); date_defau ...
- 【算法】一致性Hash算法
一.分布式算法 在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括: 轮循算法(Round Robin).哈希算法(HASH).最少连接算法(Least Connection).响应速度算法( ...
- JindoFS解析 - 云上大数据高性能数据湖存储方案
JindoFS背景 计算存储分离是云计算的一种发展趋势,传统的计算存储相互融合的的架构存在一定的问题, 比如在集群扩容的时候存在计算能力和存储能力相互不匹配的问题,用户在某些情况下只需要扩容计算能力或 ...
- linux查看java jdk jre安装路径和设置环境变量
一. 查看java jdk安装路径和设置环境变量 windows: set java_home:查看JDK安装路径 java -version:查看JDK版本 linux: whereis java ...
- 如何把EXCEL数据导入到SQL SERVER数据库中 (转)
转:http://blog.csdn.net/jjp837661103/article/details/13509889 在我们完成一个项目开发之后,通常我们需要把客户的很多数据导入到数据库中,面对大 ...
- 几个常见的漏洞(xss攻击 cookie未清除 nginx信息泄露)与处理方法
项目在安全检查中发现很多问题,要求整改,其中就有最常见的xss攻击 漏洞描述 渗透测试人员检测到网站筛选框均存在反射型跨站脚本攻击,例如: "><script>alert( ...
- 对于Final关键字的总结
1.final关键字可以用于成员变量.本地变量.方法以及类. 2. final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误. 3. 你不能够对final变量再次赋值. 4. ...
- python3_列表排序简介
说明:以下是以整数排列为例,其它数据类型读者自行思考即可知. 1.使用方法sort()对列表排序 使用格式:(注:说到方法,在列表中都是列表名.方法名()的使用格式,之后不在赘述.) 列表名.sort ...
- 2019浙江省赛 Strings in the Pocket【manacher】
Strings in the Pocket 题目链接 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=6012 题意 给你两个字符 ...