Tutorial 6: ViewSets & Routers
转载自:http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers/
Tutorial 6: ViewSets & Routers
REST framework includes an abstraction for dealing with ViewSets, that allows the developer to concentrate on modeling the state and interactions of the API, and leave the URL construction to be handled automatically, based on common conventions.
ViewSet classes are almost the same thing as View classes, except that they provide operations such as read, or update, and not method handlers such as get or put.
A ViewSet class is only bound to a set of method handlers at the last moment, when it is instantiated into a set of views, typically by using a Router class which handles the complexities of defining the URL conf for you.
Refactoring to use ViewSets
Let's take our current set of views, and refactor them into view sets.
First of all let's refactor our UserList and UserDetail views into a single UserViewSet. We can remove the two views, and replace them with a single class:
from rest_framework import viewsets
class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
This viewset automatically provides `list` and `detail` actions.
"""
queryset = User.objects.all()
serializer_class = UserSerializer
Here we've used the ReadOnlyModelViewSet class to automatically provide the default 'read-only' operations. We're still setting the queryset and serializer_class attributes exactly as we did when we were using regular views, but we no longer need to provide the same information to two separate classes.
Next we're going to replace the SnippetList, SnippetDetail and SnippetHighlight view classes. We can remove the three views, and again replace them with a single class.
from rest_framework.decorators import detail_route
from rest_framework.response import Response
class SnippetViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
Additionally we also provide an extra `highlight` action.
"""
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
@detail_route(renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
This time we've used the ModelViewSet class in order to get the complete set of default read and write operations.
Notice that we've also used the @detail_route decorator to create a custom action, named highlight. This decorator can be used to add any custom endpoints that don't fit into the standard create/update/delete style.
Custom actions which use the @detail_route decorator will respond to GET requests by default. We can use the methodsargument if we wanted an action that responded to POST requests.
The URLs for custom actions by default depend on the method name itself. If you want to change the way url should be constructed, you can include url_path as a decorator keyword argument.
Binding ViewSets to URLs explicitly
The handler methods only get bound to the actions when we define the URLConf. To see what's going on under the hood let's first explicitly create a set of views from our ViewSets.
In the urls.py file we bind our ViewSet classes into a set of concrete views.
from snippets.views import SnippetViewSet, UserViewSet, api_root
from rest_framework import renderers
snippet_list = SnippetViewSet.as_view({
'get': 'list',
'post': 'create'
})
snippet_detail = SnippetViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
})
snippet_highlight = SnippetViewSet.as_view({
'get': 'highlight'
}, renderer_classes=[renderers.StaticHTMLRenderer])
user_list = UserViewSet.as_view({
'get': 'list'
})
user_detail = UserViewSet.as_view({
'get': 'retrieve'
})
Notice how we're creating multiple views from each ViewSet class, by binding the http methods to the required action for each view.
Now that we've bound our resources into concrete views, we can register the views with the URL conf as usual.
urlpatterns = format_suffix_patterns([
url(r'^$', api_root),
url(r'^snippets/$', snippet_list, name='snippet-list'),
url(r'^snippets/(?P<pk>[0-9]+)/$', snippet_detail, name='snippet-detail'),
url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', snippet_highlight, name='snippet-highlight'),
url(r'^users/$', user_list, name='user-list'),
url(r'^users/(?P<pk>[0-9]+)/$', user_detail, name='user-detail')
])
Using Routers
Because we're using ViewSet classes rather than View classes, we actually don't need to design the URL conf ourselves. The conventions for wiring up resources into views and urls can be handled automatically, using a Router class. All we need to do is register the appropriate view sets with a router, and let it do the rest.
Here's our re-wired urls.py file.
from django.conf.urls import url, include
from snippets import views
from rest_framework.routers import DefaultRouter
# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet)
router.register(r'users', views.UserViewSet)
# The API URLs are now determined automatically by the router.
# Additionally, we include the login URLs for the browsable API.
urlpatterns = [
url(r'^', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
Registering the viewsets with the router is similar to providing a urlpattern. We include two arguments - the URL prefix for the views, and the viewset itself.
The DefaultRouter class we're using also automatically creates the API root view for us, so we can now delete the api_rootmethod from our views module.
Trade-offs between views vs viewsets
Using viewsets can be a really useful abstraction. It helps ensure that URL conventions will be consistent across your API, minimizes the amount of code you need to write, and allows you to concentrate on the interactions and representations your API provides rather than the specifics of the URL conf.
That doesn't mean it's always the right approach to take. There's a similar set of trade-offs to consider as when using class-based views instead of function based views. Using viewsets is less explicit than building your views individually.
In part 7 of the tutorial we'll look at how we can add an API schema, and interact with our API using a client library or command line tool.
Tutorial 6: ViewSets & Routers的更多相关文章
- 06_Tutorial 6: ViewSets & Routers 视图集与路由器
1.Tutorial 6: ViewSets & Routers 视图集与路由器 0.文档 https://q1mi.github.io/Django-REST-framework-docum ...
- django rest framework ViewSets & Routers
Using viewsets views.py from rest_framework import viewsets from rest_framework import mixins from r ...
- Django REST framework 第六章 ViewSets & Routers
REST framework包含了一个可以处理ViewSets的抽象, 它允许开发人员专注于API的状态跟交互进行建模,并使得URL构建结构基于通用的约定自动处理. ViewSet类跟View类几乎相 ...
- djangorestframework学习1-通过HyperlinkedModelSerializer,ModelViewSet,routers编写第一个接口
前提首先安装了django,安装方式:pip install django 1. djangorestftamework安装: pip install djangorestframework 2. 创 ...
- django-rest-framework快速入门
前言:第一次接触django-rest-framework是在实习的时候.当时也不懂,看到视图用类方法写的感觉很牛逼的样子.因为官网是英文的,这对我的学习还是有一点的阻力的,所以当时也没怎么学.真是太 ...
- django rest framework 详解
Django REST framework 是用于构建Web API 的强大而灵活的工具包. 我们可能想使用REST框架的一些原因: Web浏览API对于开发人员来说是一个巨大的可用性. 认证策略包括 ...
- Django序列化&django REST framework
第一章.Django序列化操作 1.django的view实现商品列表页(基于View类) # 通过json来序列化,但手写字典key代码量较大,容易出错:还有遇到时间,图片序列化会报错 from g ...
- django restul webservice返回json数据
做这个demo的前提是你已经配好了python ,django ,djangorestframwork(在我的上一篇博客中有介绍,大家也可以google),mysql-python等. djangor ...
- django restful webservice返回json数据
做这个demo的前提是你已经配好了python ,django ,djangorestframwork(在我的上一篇博客中有介绍,大家也可以google),mysql-python等. djangor ...
随机推荐
- Crossing Rivers HDU - 3232 (均匀分布)
题目大意:A,B相距D,A,B间有n条河,河宽Li,每条河上有一个速度为vi的船,在河山来回行驶,每条河离A的距离为pi,现在求从A到B时间的期望,步行速度始终为1 题目分析:首先如果全部步行则期望为 ...
- Qin Shi Huang's National Road System UVA - 1494(次小生成树)
秦始皇统一中国之后要在全国修公路连接各个城市,皇帝只想修成最小生成树(距离最小,不考虑人力),一个道士说自己可以不花人力物力修一条路,经过两方妥协,选择max(两个城市人口/(生成树长度-这条路的长度 ...
- 【刷题】BZOJ 2599 [IOI2011]Race
Description 给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000 Input 第一行 两个整数 n, k 第二 ...
- 【NuGet】使用NuGet打包并发布至ProGet过程 (打包再次详解)【下篇】
一.前言 上篇[1]主要介绍了利用csproj文件使用NuGet打包至ProGet的过程,并附上了用于在Jenkins上运行的python脚本.本篇的主要内容分为以下几点: 1. Nuspec与Nup ...
- 【CF55D】Beautiful numbers(动态规划)
[CF55D]Beautiful numbers(动态规划) 题面 洛谷 CF 题解 数位\(dp\) 如果当前数能够被它所有数位整除,意味着它能够被所有数位的\(lcm\)整除. 所以\(dp\)的 ...
- 【HDU5730】Shell Necklace(多项式运算,分治FFT)
[HDU5730]Shell Necklace(多项式运算,分治FFT) 题面 Vjudge 翻译: 有一个长度为\(n\)的序列 已知给连续的长度为\(i\)的序列装饰的方案数为\(a[i]\) 求 ...
- [POJ1094] Sorting It All Out
link 题目大意 给出$m$个不等式关系,问可以从第几个开始确定所有之间的大小关系.若无解请输出是无法确定还是与已知矛盾. 试题分析 这题是真的是坑啊,尽然放在$floyd$传到闭包上面,还用二分, ...
- 新的JavaScript数据结构Streams
最近在网上看到了一个新的 Javascript 小程序——Streams,起初以为是一个普通的 Javascript 类库,但读了关于它的介绍后,我发现,这不是一个简单的类库,而且作者的重点也不是这个 ...
- python基础--文件操作实现全文或单行替换
python修改文件时,使用w模式会将原本的文件清空/覆盖.可以先用读(r)的方式打开,写到内存中,然后再用写(w)的方式打开. 替换文本中的taste 为 tasting Yesterday whe ...
- python 深、浅拷贝
Python的数据结构总体分为两类: 1.字符串和数字 2.列表.元组.字典等 一.字符串和数字 对于字符串和数字而言,赋值(=).浅拷贝(copy)和深拷贝(deepcopy)其实都没有意义,因为它 ...