Viewsets - Django REST framework

Viewset-Django REST框架

viewsets.py

视图集

在路由确定了用于请求的控制器之后,您的控制器负责理解请求并生成适当的输出。

RubyonRails文档

Django REST框架允许您将一组相关视图的逻辑组合到一个单独的类中,称为视图集...在其他框架中,您可能还会发现概念上类似的实现,命名为“Resources”或“Controller”。

A 视图集类是简单的一种基于类的视图类型,它不提供任何方法处理程序。比如.get().post(),而是提供了一些操作,例如.list().create().

类的方法处理程序。视图集仅在完成视图时绑定到相应的操作,使用.as_view()方法。

通常,与其在urlconf中的视图集中显式注册视图,不如使用路由器类注册视图集,路由器类会自动为您确定urlconf。

让我们定义一个可以用于列出或检索系统中所有用户的简单视图集。

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'})

通常我们不会这样做,而是将视图集注册到一个路由器,并允许自动生成urlconf。

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

router = DefaultRouter()
router.register(r'users', UserViewSet, basename='user')
urlpatterns = router.urls

与编写自己的视图集不同,您通常希望使用提供默认行为集的现有基类。例如:

class UserViewSet(viewsets.ModelViewSet):
    """
    A viewset for viewing and editing user instances.
    """
    serializer_class = UserSerializer
    queryset = User.objects.all()

使用视图集使用View班级,等级。

  • 重复的逻辑可以组合成一个类。在上面的示例中,我们只需要指定queryset一次,它将跨多个视图使用。
  • 通过使用路由器,我们不再需要自己处理连接URL的问题。

这两件事都是有条件的。使用常规视图和URL组合更显,并给您更多的控制。如果您想要快速地启动和运行,或者当您有一个大的API并且希望在整个过程中执行一致的URL配置时,ViewSets是很有帮助的。

视图集操作

REST框架中包含的默认路由器将为一组标准的创建/检索/更新/销毁样式操作提供路由,如下所示:

class UserViewSet(viewsets.ViewSet):
    """
    Example empty viewset demonstrating the standard
    actions that will be handled by a router class.

    If you're using format suffixes, make sure to also include
    the `format=None` keyword argument for each action.
    """

    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

反思视点集动作

在分派期间,以下属性可用于视图集.

  • basename-要用于创建的URL名称的基。
  • action-当前行动的名称(例如,list, create).
  • detail-布尔值,指示当前操作是否配置为列表或详细信息视图。
  • suffix-视图集类型的显示后缀-镜像detail属性。
  • name-视图集的显示名称。这个论点是相互排斥的suffix.
  • description-对视图集的个别视图的显示描述。

您可以检查这些属性以根据当前操作调整行为。例如,可以将权限限制在除list类似的行动:

def get_permissions(self):
    """
    Instantiates and returns the list of permissions that this view requires.
    """
    if self.action == 'list':
        permission_classes = [IsAuthenticated]
    else:
        permission_classes = [IsAdmin]
    return [permission() for permission in permission_classes]

标记用于路由的额外操作

如果您有应该是可路由的即席方法,则可以将它们标记为@action装饰师。与常规操作一样,额外的操作可能是针对单个对象的,也可能是针对整个集合的。若要指示此,请设置detail争论TrueFalse...路由器将相应地配置其URL模式。例如,DefaultRouter将详细操作配置为包含pk在他们的URL模式中。

一个更完整的额外行动的例子:

from django.contrib.auth.models import User
from rest_framework import status, viewsets
from rest_framework.decorators import action
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

    @action(detail=True, 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)

    @action(detail=False)
    def recent_users(self, request):
        recent_users = User.objects.all().order_by('-last_login')

        page = self.paginate_queryset(recent_users)
        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)

装饰者还可以采取额外的参数,这些参数将仅为路由视图设置。例如:

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

这个action装饰师会GET请求,但也可以通过设置methods争论。例如:

@action(detail=True, methods=['post', 'delete'])
    def unset_password(self, request, pk=None):
       ...

然后,这两个新操作将在URL上可用。^users/{pk}/set_password/$^users/{pk}/unset_password/$

若要查看所有额外操作,请调用.get_extra_actions()方法。

为额外操作路由附加HTTP方法

额外的操作可以映射额外的HTTP方法以分离视图集方法。例如,上面的密码集/未设置方法可以合并成一个单一的路由。注意,其他映射不接受参数。

@action(detail=True, methods=['put'], name='Change Password')
    def password(self, request, pk=None):
        """Update the user's password."""
        ...

    @password.mapping.delete
    def delete_password(self, request, pk=None):
        """Delete the user's password."""
        ...

反向动作URL

如果需要获取操作的URL,请使用.reverse_action()方法。这是一个方便的包装reverse(),自动传递视图的request对象并在url_name带着.basename属性。

注意,basename期间由路由器提供。视图集登记。如果不使用路由器,则必须提供basename.as_view()方法。

使用上一节中的示例:

>>> view.reverse_action('set-password', args=['1'])
'http://localhost:8000/api/users/1/set_password'

或者,您可以使用url_name属性设置的@action装饰师。

>>> view.reverse_action(view.set_password.url_name, args=['1'])
'http://localhost:8000/api/users/1/set_password'

这个url_name主张.reverse_action()应该将相同的参数与@action装饰师。此外,此方法还可用于反转默认操作,如listcreate.


API参考

视图集

这个视图集类继承自APIView...您可以使用任何标准属性,如permission_classes, authentication_classes以控制视图集中的API策略。

这个视图集类不提供任何操作的实现。以便使用视图集类,您将重写类并显式定义操作实现。

GenericViewSet

这个GenericViewSet类继承自GenericAPIView,并提供默认的get_object, get_queryset方法和其他泛型视图基行为,但默认情况下不包括任何操作。

以便使用GenericViewSet类,您将覆盖类,或者混合所需的混合类,或者显式定义操作实现。

ModelViewSet

这个ModelViewSet类继承自GenericAPIView并通过混合各种混合类的行为,包括各种操作的实现。

所提供的行动ModelViewSet.list(), .retrieve(), .create(), .update(), .partial_update(),和.destroy().

因为ModelViewSet延展GenericAPIView,您通常至少需要提供querysetserializer_class属性。例如:

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]

    def get_queryset(self):
        return self.request.user.accounts.all()

但请注意,在移除queryset你的财产视图集,任何有关联的路由器将无法自动派生模型的Basename,因此您必须指定basename作为你的一部分路由器注册.

还请注意,尽管该类默认提供了完整的创建/列表/检索/更新/销毁操作集,但可以使用标准权限类限制可用操作。

ReadOnlyModelViewSet

这个ReadOnlyModelViewSet类还继承了GenericAPIView...同.一样ModelViewSet它还包括各种操作的实现,但不像ModelViewSet只提供“只读”操作,.list().retrieve().

同.一样ModelViewSet,您通常至少需要提供querysetserializer_class属性。例如:

class AccountViewSet(viewsets.ReadOnlyModelViewSet):
    """
    A simple ViewSet for viewing accounts.
    """
    queryset = Account.objects.all()
    serializer_class = AccountSerializer

再一次,就像ModelViewSet,您可以使用任何标准属性和方法重写GenericAPIView.

自定义视图集基类

您可能需要提供自定义视图集类没有完整的ModelViewSet操作,或以其他方式自定义行为。

若要创建提供create, listretrieve操作,继承自GenericViewSet,并混合所需的操作:

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

通过创建你自己的基地视图集类,您可以提供可在跨API的多个视图集中重用的常见行为。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QMQ2021

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值