viewsets.ViewSet 详细讲解

news/2024/11/23 23:26:57/

一、地址

官方地址: 

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 Responseclass 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 DefaultRouterrouter = 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 = UserSerializerqueryset = User.objects.all()

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

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

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

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

四、ViewSet actions

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

class UserViewSet(viewsets.ViewSet):"""Example empty viewset demonstrating the standardactions that will be handled by a router class.If you're using format suffixes, make sure to also includethe `format=None` keyword argument for each action."""def list(self, request):passdef create(self, request):passdef retrieve(self, request, pk=None):passdef update(self, request, pk=None):passdef partial_update(self, request, pk=None):passdef 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 Responseclass 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 Responseclass 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 Responseclass 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://www.ppmy.cn/news/706106.html

相关文章

python算法 -- 05 排序

冒泡排序 外层循环控制遍历的轮数,内层循环用于比较相邻元素并进行交换每一轮将剩下的元素里最大的放到最后 l [2, 45, 33, 68, 23, 45, 78, 99, 67, 10] n len(l)for i in range(n-1):for j in range(n-1-i):if l[j] > l[j1]:l[j], l[j1] l[j1], l[j]print…

单位社保缴纳明细表_职工社保缴费明细表

单位 个人 单位 20% 8% 7% XJK21331 姓名1 677*********** 10000 200 80 70 XJK21332 姓名2 678*********** 10000 200 80 70 XJK21333 姓名3 679*********** 10000 200 80 70 XJK21334 姓名4 680*********** 10000 200 80 70 XJK21335 姓名5 681*********** 10000 200 80 70 X…

办北京居住证,定制社保缴费记录,个人权益记录最近6个月的查询与打印,社保,北京市社会保险,北京市社会保险网上服务平台,北京市社会保险网上申报查询系统

20200519编辑 http://fuwu.rsj.beijing.gov.cn/csibiz/indinfo/index.jsp 必须要最近六个月的,网上是延迟2个月的,比如这个现在是5月份,就得要2020年03月和以前的(就是要包含3月份的,以前打印的是包含到1月份不行&am…

武汉市个人社保缴费证明网上打印操作流程

本文首发于:https://www.hoscen.cn/blog/hao/articles/184053017752895488.html 作者:小郝不负流年 更多相关文章请访问 www.hoscen.cn ------ 前言: 由于本人多次涉及需要打印这个证明,而每次都会忘记入口,在网上…

将收支明细进行打印或者导出表格保存

生活中的每一笔支出、收入都是需要进行记录,这样才可以很好的帮助自己管理财富,那么拥有一款好用的记账软件也是非重要的,小编今天给大家分享晨曦记账本的两个功能将收支明细进行打印以及导出表格保存。 运行【晨曦记账本】,在软件…

如何查询社保的个人编号?

目录 一、电话查询二、网上查询三、微信查询1.进入微信,点击 “我” -> “服务” -> “城市服务”2.点击 “医保综合”3.点击 “广西医保服务”4.点击 “个人信息”5.点击 “账户信息”6. “账户信息” 底部的 “人员编号” 即为社保的个人编号 有多种方式可以…

如何查询本人医保就医明细

参保人凭本人的社会保障卡(或医疗保险卡)或身份证到医保中心服务窗口提出查询本人的就医明细,医保窗口工作人员在验证查询人为持证人本人后,通过查询系统,在输入参保人社保卡号(医保卡号或身份证号&#xf…

深圳社保明细查询

地址 https://e.szsi.gov.cn/siservice/pIndex.jsp