【发布时间】: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