REST 框架包含了处理ViewSet的抽象,这样开发者就可以专注于API的状态和交互,而不用去管URL的构造,URL会按照
公共约定自动构造。
ViewSet类和View类差不多,不同的是ViewSet提供如read,update等方法,而不是get或是put。
一个ViewSet类只绑定一组方法处理程序,当它被实例化为一组views时,通常用一个Router类来处理复杂的url。
重构代码以使用ViewSets
首先将我们现有的UserList和UserDetail重构合并为UserViewSet。
编辑views.py
from rest_framework import viewsets
class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
这个ViewSet提供`list`和`detail`两个功能
"""
queryset = User.objects.all()
serializer_class = UserSerializer
这里我们使用的ReadOnlyModelViewSet类会提供默认的只读操作。
像以前一样,我们依然定义queryset和serializer_class属性,只不过之前需要在两个类里面定义,现在只需要定义一遍。
接下来我们将现有的SnippetList, SnippetDetail, SnippetHighlight重构合并为SnippetViewSet。
编辑views.py
from rest_framework.decorators import detail_route
from rest_framework.response import Response
class SnippetViewSet(viewsets.ModelViewSet):
"""
这个ViewSet自动了`list`, `create`, `retrieve`, `update`和`destroy`功能
我们需要另外定义一个`highlight`功能
"""
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)
这里我们使用的ModelViewSet类会提供默认的读写操作。
注意,我们在此同样使用了@detail_route装饰器来创建一个额外的功能,名为highlight,当标准的create, update, delete不够用时,这个装饰器能够用来添加任何额外的功能。
使用@detail_route装饰器定制的额外功能会默认使用GET请求,我们可以在装饰器的参数内定义methods参数来使用如POST等等的其它请求。
默认情况下,这种定制的额外功能会使用和方法名同名的url,如想要使用与方法名不同的url,可以在detail_route装饰器中定义url_path参数。
将ViewSets与URLs绑定
编辑urls.py
from rest_framework import renderers
from snippets.views import api_root
from snippets.views import SnippetViewSet
from snippets.views import UserViewSet
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'
})
此时我们通过将http请求方式绑定到views的方法,从ViewSet类创建了一系列views。
接下来我们将这些views注册到url中
编辑urls.py
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
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')
])
使用Router类
因为我们使用的是ViewSet类而不是View类,实际上我们不需要自己去设计URL。
通过使用Router类,我们只需要将合适的views注册到Router中,其它的事情就让它自动生成吧。
重写urls.py
from django.conf.urls import url
from django.conf.urls import include
from snippets import views
from rest_framework.routers import DefaultRouter
# 创建一个router并将viewsets注册上去
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet)
router.register(r'users', views.UserViewSet)
urlpatterns = [
url(r'^', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
DefaultRouter类自动提供了根节点的url,所以我们不再需要单独去写。
关于
本人是初学Django REST framework,Django REST framework 学习纪要系列文章是我从官网文档学习后的初步消化成果,如有错误,欢迎指正。
学习用代码Github仓库:shelmingsong/django_rest_framework
本文参考的官网文档:Tutorial 6: ViewSets & Routers
博客更新地址
- 宋明耀的博客 [ 第一时间更新 ]
- 知乎专栏 Python Cookbook
- 简书 流月0的文章








网友评论