如何使用Django Rest Framework视图集按父对象的属性过滤嵌套数据

小脑

我有嵌套的数据;列表包含许多项目。为了安全起见,我通过当前用户是否创建列表以及列表是否公开来过滤列表。我想对商品执行相同的操作,以便商品只能由经过身份验证的用户更新,如果列表是公开的,则任何人都可以查看。

这是我的视图集代码,从工作正常的列表视图集代码改编而成。这当然不适用于Item,因为该项目不具有“ created_by”或“ is_public”属性-这些是父级列表的属性。

有没有办法用列表属性替换“ created_by”和“ is_public”?即我可以在项目的get_queryset方法中获取父级列表对象,并检查其属性吗?

另一种选择是我也为该项目分配“ created_by”和“ is_public”,但是我不希望这样做,因为它是重复的数据。列表的属性应控制项目的权限。

class ItemViewSet(viewsets.ModelViewSet):
    permission_classes = [permissions.AllowAny, ]
    model = Item
    serializer_class = ItemSerializer

    def get_queryset(self):
        # restrict any method that can alter a record
        restricted_methods = ['POST', 'PUT', 'PATCH', 'DELETE']
        if self.request.method in restricted_methods:
            # if you are not logged in you cannot modify any list
            if not self.request.user.is_authenticated:
              return Item.objects.none()

            # you can only modify your own lists
            # only a logged-in user can create a list and view the returned data
            return Item.objects.filter(created_by=self.request.user)

        # GET method (view item) is available to owner and for items in public lists
        if self.request.method == 'GET':
          if not self.request.user.is_authenticated:
            return Item.objects.filter(is_public__exact=True)

          return Item.objects.filter(Q(created_by=self.request.user) | Q(is_public__exact=True))

        # explicitly refuse any non-handled methods
        return Item.objects.none()

非常感谢您的帮助!

编辑:在卢卡斯·韦恩的答案和这篇文章之间,我想我已经对此进行了整理。这是我在api.py中的工作代码:

from rest_framework import viewsets, permissions
from .models import List, Item
from .serializers import ListSerializer, ItemSerializer
from django.db.models import Q


class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        # handle permissions based on method
        # Read permissions are allowed to any request,
        # so we'll always allow GET, HEAD or OPTIONS requests.
        if request.method in permissions.SAFE_METHODS:
            return True

        if hasattr(obj, 'created_by'):
            return obj.created_by == request.user

        if hasattr(obj, 'list'):
            if hasattr(obj.list, 'created_by'):
                return obj.list.created_by == request.user

class ListViewSet(viewsets.ModelViewSet):
    permission_classes = [IsOwnerOrReadOnly]
    model = List
    serializer_class = ListSerializer

    def get_queryset(self):
        # can view public lists and lists the user created
        if self.request.user.is_authenticated:
            return List.objects.filter(
                Q(created_by=self.request.user) | 
                Q(is_public=True)
            )

        return List.objects.filter(is_public=True)

    def pre_save(self, obj):
        obj.created_by = self.request.user

class ItemViewSet(viewsets.ModelViewSet):
    permission_classes = [IsOwnerOrReadOnly]
    model = Item
    serializer_class = ItemSerializer

    def get_queryset(self):
        # can view items belonging to public lists and lists the usesr created
        if self.request.user.is_authenticated:
            return Item.objects.filter(
                Q(list__created_by=self.request.user) | 
                Q(list__is_public=True)
            )

        return Item.objects.filter(list__is_public=True)
卢卡斯·韦恩

Django允许跨越关系的查找您可以跨列表属性筛选Item对象,只需在模型之间使用相关字段的字段名称,并用双下划线将其分隔,直到获得所需的字段为止。

class ItemViewSet(viewsets.ModelViewSet):
    permission_classes = [IsOwnerOrReadyOnly]
    serializer_class = ItemSerializer

    def get_queryset(self):
        if self.request.user.is_authenticated
            return Item.objects.filter(
                Q(list__created_by=self.request.user) | 
                Q(list__is_public__exact=True)
            )

        return Item.objects.filter(list__is_public=True)

要允许项目仅由其所有者更新,请编写自定义对象级权限类

class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        # Read permissions are allowed to any request,
        # so we'll always allow GET, HEAD or OPTIONS requests.
        if request.method in permissions.SAFE_METHODS:
            return True

        # Instance must have an attribute named `created_by`.
        return obj.list.created_by == request.user

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Django Rest Framework如何过滤嵌套数据?

Django Rest Framework视图集中的对象级别授权

如何使用Django Rest Framework删除对象

在Django Rest框架中使用视图集进行过滤

如何使用 django rest 视图集执行多次插入?

如何在Django Rest Framework中动态更新视图集

如何在 Django Rest Framework 中显示嵌套对象的属性

如何使用Django Rest框架进行过滤?

Django Rest Framework:如何使用OperationHolderMixin?

如何使用Django Rest Framework更新OneToOneField

django rest框架-使用视图集

Django REST Framework:视图和视图集之间的区别?

如何使用Django REST Framework保存嵌套的Backbone模型

如何使用django-rest-framework创建登录视图

使用Django Rest框架,如何为现有父对象添加新的嵌套子对象

django rest 嵌套数据的问题

何时以及如何使用Django REST Framework验证数据

如何使用Django Rest Framework ReadOnlyModelViewSet获取“数据”而不是“结果”?

无法扩展Django REST Framework视图集以处理多级API

Django Rest Framework - 单元测试视图集额外操作

Django Rest Framework 视图集 - 基于用户名问题的外键过滤过滤器

如何按 Django REST Framework 中的列表过滤?

如何使用Django Rest Framework反序列化嵌套对象

在Django Rest Framework中过滤相关对象上的数据

如何使用 Django REST 模型创建父/子关系?

如何为 Django Rest Framework 中的视图集的自定义操作编写测试

如何在Django Rest Framework的视图集中渲染为html

如何在Django Rest Framework中更改视图集检索响应?

Django Rest Framework按日期范围过滤