【问题标题】:Filtering Django queryset with custom function使用自定义函数过滤 Django 查询集
【发布时间】:2016-06-12 20:22:22
【问题描述】:

我正在为使用自定义权限处理的现有系统开发 REST API。我正在尝试使用 Django REST 框架中的内置泛型,但在使用自定义权限过滤列表视图时遇到了麻烦。我当前观点的一个例子是:

class WidgetList(generics.ListCreateAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    model = Widget
    serializer_class = WidgetSerializer
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ('widget_type', 'widget_owner')

    def get_queryset(self):
        """
        Overwrite the query set to check permissions
        """
        qs_list = [w.id for w in self.model.objects.all() if
                   canReadWidget(self.request.user, w)]
        return self.model.objects.filter(id__in=qs_list)

这行得通,但是我觉得 get_queryset 函数可以改进。因为我的 canReadWidget 是自定义的,所以我必须评估 self.model.objects.all() 并检查用户可以阅读哪些小部件,但该函数必须返回一个查询集,所以我使用 id__in=qs_list 部分。结果是我对实际上只是一个列表提取的内容进行了两次数据库调用。

是否有一种标准方法可以为通用列表视图处理这种按对象过滤?

【问题讨论】:

  • canReadWidget 在做什么?可以发一下代码吗?
  • canReadWidget 相当复杂 - 基本上小部件存在于树中,其中一些小部件是另一种小部件类型的子级。用户可以在树中的任何级别拥有权限。所以基本上 canReadWidget(user, WidgetA) 会检查用户是否有对 WidgetA 的权限,如果有则返回 True 或 False,否则会查看 WidgetA 的父级是否有权限继承,以此类推直到找到一个或返回 false。
  • 你可以看看 django-guardian 的对象权限。但是看到您已经实现了自己的分层权限逻辑,您可能不想切换到新流程。只要您不能使用 SQL 连接(通过创建自己的 QueryManager 实现或使用自定义过滤器查询)来制定权限逻辑,就无法避免像现在这样评估和重新获取。
  • 如果你有树形层次结构,你可以用 django-mptt django-mptt.github.io/django-mptt实现更快的查询

标签: django django-rest-framework django-queryset


【解决方案1】:

在某些时候,最好放弃默认的通用视图或函数并自行开发。

您应该查看ListModelMixin 并覆盖list 来处理列表,而不是将其转换为查询集。

您应该调整过滤和分页,但您不会像现在那样访问数据库两次。

【讨论】:

    猜你喜欢
    • 2010-10-14
    • 2011-08-06
    • 2016-09-11
    • 1970-01-01
    • 1970-01-01
    • 2018-09-29
    • 1970-01-01
    • 2020-08-22
    • 2019-04-15
    相关资源
    最近更新 更多