4 Django REST Framework 开发 ---- ViewSet

After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output.

Routing 的职责是,决定哪一个 controller 应该对于收到的 request 做出回应,所以 controller 的作用是处理 request 并产生相对的 output 回应。
Aus <https://www.django-rest-framework.org/api-guide/viewsets/>


DRF 允许多个相关的 View 共同完善某个类的功能(多继承,类似 Java 的接口),并将诸多功能封装在单个类中,这样的类叫做 ViewSet。
一个 ViewSet 的类其实是某种 class-based View,该 View 不提供任何方法的 Handler 如:.get(), .post(), 但是提供 actions 如:.list(), .create()。 这些 actions 有助于使你的程序变得更加动态 (比如动态设置 Serilizer 会变得很方便)。
ViewSet 方法的 handler 则使用 .as_view()方法绑定到 View 的最终的相应操作上。一般 viewset 不在 urlconf 中配置,而是将其通过 router 类注册到应用程序上,router 会负责根据用户请求分发给相应 url。

相关知识点:ViewSetMixin
ViewSetMixin 重写 as_view 的信息,来达到定制路由的效果, 这个能让我们注册 url 变得更加简单。ViewSetMixin的源码部分如下:

1 class ViewSetMixin(object):
2     @classonlymethod
3     def as_view(cls, actions=None, **initkwargs):
4       ······
5         if not actions:
6             raise TypeError("The `actions` argument must be provided when "
7                             "calling `.as_view()` on a ViewSet. For example "
8                             "`.as_view({'get': 'list'})`")
9       ······


能看到在actions字段可以设置 {'get': 'list'} 这样的路由规则。

比如 urls.py 文件中配置:

my_product_list = ProductListViewSet.as_view({ 'get': 'list' })

另一种方法为创建 DefaultRouter 对象,然后用该对象注册 url。这种方法在工业中更被广泛地使用。

router = DefaultRouter()
router.register(r'product', ProductListViewSet) 

详见 Router 章节

ViewSetMixin 还有一个方法是initialize_request,这个方法主要是给 action 属性赋值,这个属性在设置动态 serializer 和 permission 的时候有很大的用处。

相关知识点 GenericViewSet:

GenericViewSet 类继承 GenericAPIView 和 ViewSetMixin,且提供了 get_object, get_queryset 方法以及其他的 generic view 的特征,但不会默认包括 action(所以需要通过继承特定类来实现)
在使用时必须重写该类,并且要么继承 mixin 类要么就自定义 action。

源码如下:

1 class GenericViewSet(ViewSetMixin, gernerics.GenericAPIView)
2     pass

由于 ViewSetMixin 类,这样继承了 GenericViewSet 的类就可以直接使用 router 对象配置 url 以及绑定 action。
由于 GenericAPIView 类, 这样继承了 GenericViewSet 的类就具有 queryset,serializer 以及 Pagination 的功能。

修改 views.py 文件:

1 class ProductListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
2     queryset = Product.objects.all()
3     serializer_class = ProductSerializer
4     pagination_class = ProductPagination

由于继承了 ListModelMixin 这样就自动有了 .list(request, *args, **kwargs) 的 action 方法。所以仅这段加上正确的 Router 配置,就可以实现展示商品 List 的效果。这也是它强于 GenericAPIView 的地方(即省略了 get -> list, post -> create 等函数的绑定)。

Extra 知识点 Routers:

由于 ViewSet 的 as_view() 方法,我们在 URL 配置时会简化很多操作,因为所有需要对 ViewSet 与 URL 的配置都可以使用 Router 类自动处理,这也使我们的代码变得更加规范。

例如:在 urls.py 文件中做下面操作:

 1 from rest_framework.routers import DefaultRouter
 2 
 3 router = DefaultRouter()
 4 router.register(r'products', views.ProductListViewSet)
 5 
 6 urlpatterns = [
 7     url(r'^admin/', admin.site.urls),
 8     url(r'^docs/', include_docs_urls(title="My Project")),
 9     url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
10     url(r'^', include(router.urls)),  # 所有在 router 对象上注册了的 ViewSet 都会被配置到 urlpatterns 中
11 ]

 在开发中 ViewSet 因为封装了大部分需要的操作,这些功能是它比 APIView 开发时更高效。一般只有在 ViewSet 的功能不够需要自定义一些特殊功能的时候,才会去自行编写稍微底层一点的 APIView 类。

猜你喜欢

转载自www.cnblogs.com/crazy-chinese/p/9828138.html