041、Django REST framwork 的视图集

    xiaoxiao2025-08-17  16

    一、视图集ViewSet

    视图集:将操作同一组资源的处理方法放在同一个类中,这个类叫做视图集。如:

    前面在实现图书管理的5个API时,需要两个类视图,而如果视图集,只需要一个即可。

    1. 基本使用

    1)继承视图集父类ViewSet(继承自ViewSetMixin和APIView)。

    2)视图集中的处理方法不再以对应个请求方式(get、post等)命名,而是以对应的操作(action)命名。

    list:提供一组数据retrieve:提供单个数据create:创建数据update:保存数据destory:删除数据

    3)在进行URL配置时,需要明确指明某个请求方式请求某个URL地址时,对应的是视图集中的哪个处理函数。

    如:

    from rest_framework import viewsets from booktest.models import BookInfo from booktest.serializers import BookInfoSerializer class BookInfoViewSet(viewsets.ViewSet): def list(self, request): books = BookInfo.objects.all() serializer = BookInfoSerializer(books, many=True) return Response(serializer.data) def retrieve(self, request, pk=None): try: books = BookInfo.objects.get(id=pk) except BookInfo.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) serializer = BookInfoSerializer(books) return Response(serializer.data)

    在设置路由时,可以如下操作:

    from booktest import views urlpatterns = [ url(r'^books/$', views.BookInfoViewSet.as_view({'get':'list'}), url(r'^books/(?P<pk>\d+)/$', views.BookInfoViewSet.as_view({'get': 'retrieve'}) ]

    2. 常用视图集父类

    1) ViewSet

    继承自APIView与ViewSetMixin,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。

    2)GenericViewSet

    继承自GenericAPIView与ViewSetMixin,可以直接搭配Mixin扩展类使用。

    如:

    from rest_framework import mixins from rest_framework.viewsets import GenericViewSet from rest_framework.decorators import action class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet): queryset = BookInfo.objects.all() serializer_class = BookInfoSerializer

    url的配置:

    urlpatterns = [ url(r'^books/$', views.BookInfoViewSet.as_view({'get': 'list'})), url(r'^books/(?P<pk>\d+)/$', views.BookInfoViewSet.as_view({'get': 'retrieve'})), ]

    3)ModelViewSet

    继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

    4)ReadOnlyModelViewSet

    继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin。

    3. 视图集中添加额外的处理方法

    在视图集中,除了上述默认的方法动作外,还可以添加额外的处理方法。

    如:

    from rest_framework import mixins from rest_framework.viewsets import GenericViewSet from rest_framework.decorators import action class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet): queryset = BookInfo.objects.all() serializer_class = BookInfoSerializer def latest(self, request): """ 返回最新的图书信息 """ book = BookInfo.objects.latest('id') serializer = self.get_serializer(book) return Response(serializer.data) def read(self, request, pk): """ 修改图书的阅读量数据 """ book = self.get_object() book.bread = request.data.get('read') book.save() serializer = self.get_serializer(book) return Response(serializer.data)

    url的配置:

    urlpatterns = [ url(r'^books/$', views.BookInfoViewSet.as_view({'get': 'list'})), url(r'^books/latest/$', views.BookInfoViewSet.as_view({'get': 'latest'})), url(r'^books/(?P<pk>\d+)/$', views.BookInfoViewSet.as_view({'get': 'retrieve'})), url(r'^books/(?P<pk>\d+)/read/$', views.BookInfoViewSet.as_view({'put': 'read'})), ]

    4. 视图集对象action属性

    在视图集中,可以通过视图集对象.action获取所有执行action的操作。应用场景:重写get_serializer_class和get_queryset,根据不同的action操作返回不同的序列化器类和不同的查询集。

    如:

    def get_serializer_class(self): if self.action == 'list': return '<list操作所使用的序列化器类>' else: return '<其他操作所使用的序列化器类>' def get_queryset(self): if self.action == 'list': return '<list操作所使用的查询集>' else: return '<其他操作所使用的查询集>'

    二、路由Routers

    对于视图集ViewSet,除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用路由Router来自动生成路由信息。

    REST framework提供了两个Router类:

    SimpleRouterDefaultRouter

    1. 基本使用

    1)创建Router对象,并注册视图集。

    from rest_framework.routers import SimpleRouter router = SimpleRouter() router.register(r'books', BookInfoViewSet, base_name='book')

    register(prefix, viewset, base_name)

    prefix:该视图集的路由前缀viewset:视图集base_name:路由name名称的前缀

    上述代码会生成的路由如下:

    ^books/$ name: book-list

    ^books/{pk}/$ name: book-detail

    2)添加路由数据

    urlpatterns = [ ... ] urlpatterns += router.urls

    2. 视图集中额外处理方法配置项生成

    在视图集中,如果想要让Router自动帮助我们为自定义的处理方法生成路由信息,需要使用rest_framework.decorators.action装饰器。

    action装饰器可以接收两个参数:

    methods: 声明该action对应的请求方式,列表传递。detail: 声明该action的路径是否与单一资源对应,及是否是xxx/<pk>/action方法名/。 True 表示路径格式是xxx/<pk>/action方法名/False 表示路径格式是xxx/action方法名/

    如:

    from rest_framework import mixins from rest_framework.viewsets import GenericViewSet from rest_framework.decorators import action class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet): queryset = BookInfo.objects.all() serializer_class = BookInfoSerializer # detail为False 表示路径名格式应该为 books/latest/ @action(methods=['get'], detail=False) def latest(self, request): """ 返回最新的图书信息 """ ... # detail为True,表示路径名格式应该为 books/{pk}/read/ @action(methods=['put'], detail=True) def read(self, request, pk): """ 修改图书的阅读量数据 """ ...

    由路由器自动为此视图集自定义action处理方法生成的路由如下:

    ^books/latest/$ name: book-latest

    ^books/{pk}/read/$ name: book-read

    3. 路由router形成URL的方式

    1) SimpleRouter

    2)DefaultRouter

    DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。

    最新回复(0)