ViewSets

2018-02-28  本文已影响0人  lkning

1.简介

- 一般不需要在路由管理器中另外注册视图函数,只需要注册这个viewset类就够了,然后就会自动帮你处理,例如:

# 定义一个简单的list和retrieve视图
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from myapps.serializers import UserSerializer
from rest_framework import viewsets
from rest_framework.response import Response

class UserViewSet(viewsets.ViewSet):
    """
    A simple ViewSet for listing or retrieving users.
    """
    def list(self, request):
        queryset = User.objects.all()
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        queryset = User.objects.all()
        user = get_object_or_404(queryset, pk=pk)
        serializer = UserSerializer(user)
        return Response(serializer.data)

如果我们需要可以提取出来成为两个单独的部分,需要传入参数,方法名:函数名

user_list = UserViewSet.as_view({'get': 'list'})
user_detail = UserViewSet.as_view({'get': 'retrieve'})

一般我们使用Router类自动帮我们处理路由

from myapp.views import UserViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
# 默认使用model小写复数, base_name为小写单数
router.register(r'users', UserViewSet, base_name='user')
urlpatterns = router.urls

ViewSet和View视图类的区别:

2. 为路由添加额外的功能

REST框架默认提供了create/retrieve/update/destroy等操作

class UserViewSet(viewsets.ViewSet):
    """
    一个空的演示实例,将会被路由类处理

    如果使用过了后缀,确保每一个函数后面有一个`format=None`参数
    """

    def list(self, request):
        pass

    def create(self, request):
        pass

    def retrieve(self, request, pk=None):
        pass

    def update(self, request, pk=None):
        pass

    def partial_update(self, request, pk=None):
        pass

    def destroy(self, request, pk=None):
        pass

如果临时有一个方法需要被路由处理,可以使用@detail_route@list_route装饰器
@detail_route包含一个pk,此方法为操作单个实例的方法
@list_route,是操作一系列对象的方法,如:

from django.contrib.auth.models import User
from rest_framework import status
from rest_framework import viewsets
from rest_framework.decorators import detail_route, list_route
from rest_framework.response import Response
from myapp.serializers import UserSerializer, PasswordSerializer

class UserViewSet(viewsets.ModelViewSet):
    """
    A viewset that provides the standard actions
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @detail_route(methods=['post'])
    def set_password(self, request, pk=None):
        user = self.get_object()
        serializer = PasswordSerializer(data=request.data)
        if serializer.is_valid():
            user.set_password(serializer.data['password'])
            user.save()
            return Response({'status': 'password set'})
        else:
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)

    # 最近登录的用户
    @list_route()
    def recent_users(self, request):
        recent_users = User.objects.all().order('-last_login')

        page = self.paginate_queryset(recent_users)
        # page为分页好的一些列对象
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(recent_users, many=True)
        return Response(serializer.data)

此装饰器也能为路由视图添加额外的视图。

@detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
   ...

装饰器默认处理get请求,但也通过methods参数接受其他请求方法

# 删除密码
@detail_route(methods=['post', 'delete'])
def unset_password(self, request, pk=None):
   ...

这两个新的函数的路由地址为:
^users/{pk}/set_password/users/pk/unsetpassword/

3.API参考

class AccountViewSet(viewsets.ModelViewSet):
    """
    A simple ViewSet for viewing and editing accounts.
    """
    queryset = Account.objects.all()
    serializer_class = AccountSerializer
    permission_classes = [IsAccountAdminOrReadOnly]

你可以对GenericAPIView提供的各种方法和属性进行重写。

class AccountViewSet(viewsets.ModelViewSet):
    """
    A simple ViewSet for viewing and editing the accounts
    associated with the user.
    """
    serializer_class = AccountSerializer
    permission_classes = [IsAccountAdminOrReadOnly]

    # 动态的获取查询集,视图类中必须提供get_queryset方法或者queryset属性
    def get_queryset(self):
        return self.request.user.accounts.all()

注意:当我们删除ViewSet的queryset属性时, 任何与此相关的路由都自动无法获得数据库模型的base_name,所以在路由注册时,我们必须设置base_name参数。
虽然类视图默认提供了各种create/list/retrieve/update/destroy操作,你也可以通过permission_classes管理用户操作权限

class AccountViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Account.objects.all()
    serializer_class = AccountSerializer

4. 自定义个性化视图实例

from rest_framework import mixins

class CreateListRetrieveViewSet(mixins.CreateModelMixin,
                                mixins.ListModelMixin,
                                mixins.RetrieveModelMixin,
                                viewsets.GenericViewSet):
    """
    A viewset that provides `retrieve`, `create`, and `list` actions.

    To use it, override the class and set the `.queryset` and
    `.serializer_class` attributes.
    """
    pass

摘自

上一篇 下一篇

猜你喜欢

热点阅读