viewsets.ViewSet 详细讲解

news/2024/7/5 9:25:48

一、地址

官方地址: 

Viewsets - Django REST framework

相关文章:

二、ViewSets介绍

引入:

from rest_framework import viewsets

ViewSet 类只是一种类基础视图,它不提供任何方法处理程序(如 .get() 或 .post()),而是提供诸如 .list() 和 .create() 等操作。

ViewSet 的方法处理程序只在最终确定视图时与相应的操作绑定,使用 .as_view() 方法。

通常,您不需要在 urlconf 中显式注册 ViewSet 中的视图,而是将 ViewSet 注册到路由器类中,该类会自动确定 urlconf。

三、应用

3.1 视图

举例:

实现两个方法。

  • list:列出所有用户的列表,
  • retrieve:检索某一个用户的详细信息,
from rest_framework import viewsets
from rest_framework.response import Response

class UserViewSet(viewsets.ViewSet):
    def list(self, request):
        # 从系统中获取所有用户
        queryset = User.objects.all()
        # 序列化查询集
        serializer = UserSerializer(queryset, many=True)
        # 将序列化的数据作为响应返回
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        # 根据主键(pk)获取系统中的单个用户
        try:
            user = User.objects.get(pk=pk)
        except User.DoesNotExist:
            # 处理用户不存在的情况
            return Response(status=status.HTTP_404_NOT_FOUND)
        # 序列化用户对象
        serializer = UserSerializer(user)
        # 将序列化的数据作为响应返回
        return Response(serializer.data)

在上面的示例中,我们定义了一个 UserViewSet 类,它继承自 viewsets.ViewSet。在类内部,我们定义了两个方法:list()retrieve()

list() 方法负责返回系统中所有用户的列表。它使用 User.objects.all() 查询集从数据库中获取所有用户对象,使用 UserSerializer 对查询集进行序列化,并将序列化的数据作为响应返回。

retrieve() 方法负责根据主键(pk)检索单个用户。它尝试根据提供的主键从数据库中获取用户对象。如果用户不存在,则返回 404 Not Found 响应。如果用户存在,则使用 UserSerializer 对用户对象进行序列化,并将序列化的数据作为响应返回。

您可以使用路由器将此 ViewSet 注册,以自动生成用于列出和检索用户的必要 URL。

3.2 路由

方式一:

如果需要的话,我们可以将这个 viewset 绑定到两个独立的视图中,像这样:

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

方式二: 

 通常情况下,我们不会这样做,而是使用路由器注册 viewset,并允许自动生成 URL 配置。

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

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

与其编写自己的 viewset,通常更好的做法是使用现有的基类,这些基类提供了一组默认的行为。例如

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

使用 ViewSet 类而不是 View 类有两个主要优势。

首先,可以将重复的逻辑合并到一个类中。在上面的示例中,我们只需要指定一次查询集,它将在多个视图中使用。

其次,通过使用路由器,我们不再需要手动处理 URL 配置。

这两者都有一个权衡。使用常规的视图和 URL 配置更加明确,可以更好地控制。ViewSet 在您希望快速启动或具有大型 API 并且希望强制执行一致的 URL 配置时非常有用。

四、ViewSet actions

REST framework 中提供的默认路由器将为一组标准的创建/检索/更新/删除样式的操作提供路由,如下所示:

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

五、反射ViewSet actions

在调度期间,ViewSet 上可以使用以下属性:

  • basename - 用于创建 URL 名称的基础部分。
  • action - 当前动作的名称(例如,list、create)。
  • detail - 布尔值,指示当前动作是否为列表视图或详细视图配置的。
  • suffix - 视图集类型的显示后缀 - 与 detail 属性相同。
  • name - 视图集的显示名称。该参数与 suffix 互斥。
  • description - 视图集中各个视图的显示描述。

您可以检查这些属性以根据当前动作调整行为。例如,您可以类似于以下示例将权限限制为除了 list 动作之外的所有权限:

def get_permissions(self):
    """
    实例化并返回此视图所需的权限列表。
    """
    if self.action == 'list':
        permission_classes = [IsAuthenticated]
    else:
        permission_classes = [IsAdminUser]
    return [permission() for permission in permission_classes]

以上示例中,get_permissions() 方法根据当前动作(self.action)来确定要应用的权限类。如果当前动作是 list,则使用 IsAuthenticated 权限类;否则,使用 IsAdminUser 权限类。最后,将权限类实例化并作为列表返回。

六、自定义actions

标记额外的操作以进行路由配置

在 ViewSet 中,您可以定义自定义的动作(除了默认的 create/retrieve/update/destroy 操作),并使用装饰器 @action@detail_route@list_route 标记它们以进行路由配置。

from rest_framework.decorators import action
from rest_framework.response import Response

class MyViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer

    # 自定义动作标记为 detail_route,表示它适用于详细视图
    @detail_route(methods=['post'])
    def custom_action(self, request, pk=None):
        instance = self.get_object()
        # 执行自定义操作
        # ...

        return Response({'message': 'Custom action executed successfully'})

上述示例中,custom_action 被标记为 @detail_route,表示它是一个针对详细视图的自定义动作。您可以使用此装饰器指定不同的 HTTP 方法(如 methods=['post'])和其他选项来配置路由和视图行为。

注意:在最新的版本中,推荐使用 @action 装饰器替代 @detail_route@list_route。例如,上面的示例可以改写为:

from rest_framework.decorators import action
from rest_framework.response import Response

class MyViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer

    # 自定义动作标记为 action,不再需要指定方法(默认支持 GET)
    @action(detail=True, methods=['post'])
    def custom_action(self, request, pk=None):
        instance = self.get_object()
        # 执行自定义操作
        # ...

        return Response({'message': 'Custom action executed successfully'})

使用 @action 装饰器可以更清晰地指定一个动作,并且提供了更多的选项来配置路由和视图行为。

如果您有一些临时方法需要进行路由配置,可以使用@action装饰器将它们标记为可路由的。与普通的操作一样,额外的操作可以针对单个对象或整个集合进行。为了指示这一点,将detail参数设置为TrueFalse。路由将相应地配置其URL模式,例如,DefaultRouter将在URL模式中包含pk来配置详细操作。

以下是使用额外操作的更完整示例:

from rest_framework.decorators import action
from rest_framework.response import Response

class MyViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer

    # 针对整个集合的额外操作
    @action(detail=False, methods=['get'])
    def custom_action_collection(self, request):
        # 在整个对象集合上执行自定义操作
        # ...

        return Response({'message': '在集合上成功执行自定义操作'})

    # 针对单个对象的额外操作
    @action(detail=True, methods=['get'])
    def custom_action_object(self, request, pk=None):
        instance = self.get_object()
        # 在单个对象上执行自定义操作
        # ...

        return Response({'message': '在对象上成功执行自定义操作'})

在上面的示例中,通过在@action装饰器中设置detail=False,我们将custom_action_collection方法标记为整个集合的额外操作。此操作将在与ViewSet关联的URL模式上可访问,而无需任何对象标识符。

另一方面,custom_action_object方法通过在@action装饰器中设置detail=True将其标记为单个对象的额外操作。此操作将在与ViewSet关联的URL模式上可访问,并且将包括对象标识符(例如,/mymodels/1/custom_action_object/)。

通过使用@action装饰器,您可以在ViewSet中定义和配置超出标准CRUD操作的额外操作。

@action装饰器默认会路由GET请求,但也可以通过设置methods参数接受其他HTTP方法。例如:

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

该装饰器允许您覆盖任何视图集级别的配置,例如permission_classes、serializer_class、filter_backends等:

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

然后,这两个新操作将在以下URL上可用:^users/{pk}/set_password/$ 和 ^users/{pk}/unset_password/$。您可以使用url_path和url_name参数来更改操作的URL片段和反向URL名称。

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

七、使用额外操作,可以将其他HTTP方法映射到单独的ViewSet方法。

例如,上述密码设置/取消方法可以合并为一个路由。请注意,附加映射不接受参数。

@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."""
    ...

在上面的示例中,我们定义了名为"Change Password"的额外操作,并将其映射到PUT方法。在方法体内,我们可以执行更新用户密码的逻辑。

同时,我们使用.mapping.delete装饰器将额外操作delete_password映射到DELETE方法。在该方法内,我们可以执行删除用户密码的逻辑。

通过这种方式,您可以为额外操作定义不同的HTTP方法,以满足您的需求。

八、获取操作的URL

如果您需要获取操作的URL,请使用.reverse_action()方法。这是reverse()方法的一个便利包装,它会自动传递视图的请求对象,并在url_name之前添加.basename属性。

请注意,basename是在ViewSet注册期间由路由器提供的。如果您没有使用路由器,则必须在.as_view()方法中提供basename参数。

使用前面一节的示例:

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

另外,您还可以使用由@action装饰器设置的url_name属性。

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

.reverse_action()方法的url_name参数应与@action装饰器的相同参数匹配。此外,该方法还可用于反转默认操作,例如list和create。


http://lihuaxi.xjx100.cn/news/1304849.html

相关文章

MySQL数据库总结 之 约束(restraint) 外键约束

前三篇关于MySQL的博客,地址如下: 1. MySQL数据库 && SQL语言命令总结 && 数据类型、运算符和聚合函数汇总_Flying Bulldog的博客-CSDN博客 2. 从0到1 && 关于MySQL的数据库和表_Flying Bulldog的博客-CSDN博客 3. MySQL数据…

Idea整合Maven安装及配置教程(图文详解)

目录 友情提醒第一章、Maven概述1.1)Maven是什么1.2)Maven进行构建(build)的主要环节 第二章、Maven的下载安装和配置2.1)Maven的下载2.2)Maven环境变量配置2.3)Maven文件setting的配置 第三章、…

乐视三合一体感深度相机AstraPro图像获取流程【必看】

1、下载ros包或者自己去github 如果不能科学上网,可以在这里下载所有源代码。 下载链接:https://download.csdn.net/download/ryanji/87990936 git clone https://github.com/orbbec/ros_astra_camera.git git clone https://github.com/libuvc/libuvc.…

【WSN定位】基于浣熊优化算法的多通信半径和跳距加权Dvhop定位算法【Matlab代码#46】

文章目录 【可更换其他算法,获取资源请见文章第6节:资源获取】1. Dvhop定位算法2. 原始浣熊优化算法2.1 开发阶段2.2 探索阶段 3. 多通信半径和跳距加权策略3.1 多通信半径策略3.2 跳距加权策略 4. 部分代码展示5. 仿真结果展示6. 资源获取 【可更换其他…

Linux-CentOS/统信UOS(v20-1060a/e)安装.net core 6.0运行环境

打开终端,输入以下指令,将Microsoft包的签名密钥添加到受信任密钥列表,同时添加Microsoft包存储库 //如果是管理员账号 例如 root 登录的系统,那么前面的sudo可以省略 sudo rpm -Uvh https://packages.microsoft.com/config/cent…

Distractor-aware Siamese Networks for Visual Object Tracking(DaSiamRPN)

Distractor-aware Siamese Networks for Visual Object Tracking(DaSiamRPN,ECCV2018) 该论文针对以下三个问题,分别进行了改进: 常见的Siam类跟踪方法只能区分目标和无语义信息的背景(即简单背景&#x…

MMdetection框架速成系列 第04部分:配置文件详细解析+文件结构剖析+Config类核心实现

🚗🚗🚗🚗🚗🚗🚗🚗🚗🚗🚗🚗🚗🚗🚗🚗🚗 MMdetection框架速成系列 MMdetect…

正则表达式和BeautifulSoup

文章目录 1、正则表达式介绍2、正则表达式和BeautifulSoup3、获取属性4、Lambda表达式 1、正则表达式介绍 正则表达式是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。它描述了一种字符串匹配的模式(pattern),可以用来…