对于您的第一个问题,关于连接UserViewSet,您可以在urls文件中如下使用:
urlpatterns = [
url(
r'^users/$',
UserViewSet.as_view({'get': 'list'}),
name='user-list',
),
url(
r'^users/(?P<pk>\d+)/$',
UserViewSet.as_view({'get': 'retrieve'}),
name='user-detail',
),
]
这是您的用户模型的只读实现,使用ViewSets。如果您想列出所有用户,可以请求/users/
,如果您想获取id为1的用户,则应请求/users/1/
。
您应该明白这里有两种操作:对您的模型进行操作,例如列出用户或创建新用户;以及对模型实例进行操作。例如,如果您想检索、更新或删除用户实例,您需要在URL中包含用户的主键,以便获取该用户。
您的TaskViewSet不是只读的,因此让我们看看该类应该是什么样子。
class TaskViewSet(ModelViewSet):
queryset = Task
serializer_class = TaskSerializer
lookup_field = 'pk'
lookup_url_kwarg = 'pk'
以下是您可以在urls文件中实现的简单通用的ModelViewSet:
urlpatterns = [
url(
r'^tasks/$',
TaskViewSet.as_view({'get': 'list', 'post': 'create'}),
name='task-list',
),
url(
r'^tasks/(?P<pk>\d+)/$',
TaskViewSet.as_view({'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'}),
name='task-detail',
),
]
现在您可以对您的模型进行任何操作,包括列出、创建、检索、更新和删除对象。使用ModelViewSet,您会发现有一种模式正在形成,这就是路由器的便利之处。Django Rest Framework的路由器实现基本上通过获取路径和ViewSet,然后构造URL来工作。
在此示例中,我们使用SimpleRouter生成我们的URL模式。
router = SimpleRouter()
router.register('users', UserViewSet)
router.register('tasks', TaskViewSet)
urlpatterns = [] + router.urls
这将生成:
urlpatterns = [
url(
r'^users/$',
UserViewSet.as_view({'get': 'list'}),
name='user-list',
),
url(
r'^users/(?P<pk>\d+)/$',
UserViewSet.as_view({'get': 'retrieve'}),
name='user-detail',
),
url(
r'^tasks/$',
TaskViewSet.as_view({'get': 'list', 'post': 'create'}),
name='task-list',
),
url(
r'^tasks/(?P<pk>\d+)/$',
TaskViewSet.as_view({'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'}),
name='task-detail',
),
]
到目前为止,我希望这些内容都能让你理解,你可以看到如何使用这些类来减少需要编写的代码。
现在我将解释 @detail_route
和 @list_route
装饰器的作用。这些装饰器帮助 Router 类在您的 ViewSet 上注册自定义方法。
对于 rest framework 3.8 以上版本,@detail_route
和 @list_route
已经被弃用,取而代之的是 @action
装饰器。使用 @action(detail=True, ...)
代替 @detail_route(...)
,使用 @action(detail=False, ...)
代替 @list_route(...)
。
如果您想要提供一些以 CSV 格式下载模型报告数据为例,应使用 @list_route
装饰器来调用 Model 上有意义的操作,而不是该模型的实例。 如果您想要针对 Model 的实例执行操作,则应使用 @detail_route
装饰器。 我将扩展之前的 TaskViewSet 示例。
class TaskViewSet(ModelViewSet):
queryset = Task
serializer_class = TaskSerializer
lookup_field = 'pk'
lookup_url_kwarg = 'pk'
@list_route(methods=['get'])
def download(self, request, *args, **kwargs):
"""Download queryset as xlsx"""
qs = self.get_queryset()
return queryset_to_excel(qs)
@detail_route(methods=['get'])
def details(self, request, *args, **kwargs):
"""Return intricate details of Task"""
object = self.get_object()
return object.get_intricate_task_details()
如果我们使用此 TaskViewSet 与路由器:
router = SimpleRouter()
router.register('tasks', TaskViewSet)
urlpatterns = [] + router.urls
我已经在列表上添加了一个下载方法,可以将查询集以Excel文件的形式下载,并且我还添加了一个详细信息方法到详情视图中,它会返回一些可能很耗费资源的额外信息,因此我们不希望它出现在普通的详细响应中。然后我们将得到一个如下的URL配置:
urlpatterns = [
url(
r'^tasks/$',
TaskViewSet.as_view({'get': 'list', 'post': 'create'}),
name='task-list',
),
url(
r'^tasks/download/$',
TaskViewSet.as_view({'get': 'download'}),
name='task-download',
),
url(
r'^tasks/(?P<pk>\d+)/$',
TaskViewSet.as_view({'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'}),
name='task-detail',
),
url(
r'^tasks/(?P<pk>\d+)/details/$',
TaskViewSet.as_view({'get': 'detail'}),
name='task-details',
),
]
路由器现在已经为TaskViewSet上定义的自定义方法生成了额外的路由。
我建议阅读有关ViewSet和SimpleRouter的rest框架文档。
http://www.django-rest-framework.org/api-guide/viewsets/#modelviewset
http://www.django-rest-framework.org/api-guide/routers/#simplerouter