REST 框架的 ViewSets
允许开发人员集中精力对 API 的状态和交互进行建模,并根据常规约定自动处理 URL 构造。
ViewSet
类与 View
类几乎相同,不同之处在于它们提供诸如 read
或 update
之类的操作,而不是 get
或 put
等方法处理程序。
最后一个 ViewSet
类只绑定到一组方法处理程序,当它被实例化成一组视图的时候,通常通过使用一个 Router
类来处理自己定义 URL conf
的复杂性。
使用 ViewSets 重构
我们看一下目前的视图,把它们重构成视图集。
首先让我们将 UserList
和 UserDetail
视图重构为一个 UserViewSet
。我们可以删除这两个视图,并用一个类替换它们:
# apis.py
from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import viewsets # 视图集
class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
此视图自动提供`list`和`detail`操作。
(这里的文字会显示在 API 页面上)
"""
queryset = User.objects.all()
serializer_class = UserSerializer
接下来类似的替换掉 BookList
和 BookDetail
:
# apis.py
from rest_framework import viewsets # 视图集
from myapp.models import Book
from myapp.serializers import BookSerializer
from rest_framework import permissions # 权限模块
from myapp.permissions import IsOwnerOrReadOnly # 自定义权限
class BookViewSet(viewsets.ModelViewSet):
"""
此视图自动提供`list`,`create`,`retrieve`,`update`和`destroy`操作。
"""
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
将 ViewSets 绑定到 URL
在 urls.py
文件中,我们将 ViewSet
类绑定到一组具体视图中。
# urls.py
from myapp.apis import BookViewSet, UserViewSet, api_root
book_list = BookViewSet.as_view({
'get': 'list',
'post': 'create'
})
book_detail = BookViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
})
user_list = UserViewSet.as_view({
'get': 'list'
})
user_detail = UserViewSet.as_view({
'get': 'retrieve'
})
请注意,我们是如何通过将 http 方法绑定到每个视图所需的操作,从每个 ViewSet
类创建多个视图的。
现在我们将资源绑定到具体的视图中,我们可以像往常一样在 URL conf
中注册视图。
# urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
# API 根目录
url(r'^api/$', api_root),
# 所有 user 的 API
url(r'^api/users/$', user_list, name='user-list'),
# 单个 user 的 API
url(r'^api/users/(?P<pk>[0-9]+)/$', user_detail, name='user-detail'),
# 所有 book 的 API
url(r'^api/books/$', book_list, name='book-list'),
# 单个 book 的 API
url(r'^api/book/(?P<pk>[0-9]+)/$', book_detail, name='book-detail'),
]
使用路由
因为我们使用的是 ViewSet
类而不是 View
类,我们实际上不需要自己设计 URL。将资源连接到视图和 url 的约定可以使用 Router
类自动处理。我们需要做的就是使用路由器注册相应的视图集,然后让它执行其余操作。
这是我们重写的 urls.py
文件。
from django.conf.urls import url
from django.contrib import admin
from rest_framework.routers import DefaultRouter
from myApp import apis
router = DefaultRouter()
router.register(r'^api/users', apis.UserViewSet)
router.register(r'^api/books', apis.BookViewSet)
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
urlpatterns = urlpatterns + router.urls