【发布时间】:2019-06-09 03:28:06
【问题描述】:
我有节点和用户模型,它们都属于一个组织。我想确保用户只会看到属于其组织的节点实例。
为此,我想用一个返回用户拥有的过滤结果的 query_set 的节点对象管理器来覆盖节点对象管理器。
基于https://docs.djangoproject.com/en/2.1/topics/db/managers/#modifying-a-manager-s-initial-queryset 我拥有的相关 models.py 代码如下:
class Organisation(models.Model):
users = models.ManyToManyField(User, related_name='organisation')
...
class UserNodeManager(models.Manager):
def get_queryset(self, request):
return super().get_queryset().filter(organisation=self.request.user.organisation.first())
class Node(models.Model):
organisation = models.ForeignKey(
Organisation, related_name='nodes', on_delete=models.CASCADE)
uuid = models.UUIDField(primary_key=True, verbose_name="UUID")
...
objects = UserNodeManager
views.py
class NodeListView(LoginRequiredMixin, generic.ListView):
model = Node
编辑 我可以将自定义 query_set 添加到单个视图中,这确实如下所示:
views.py
class NodeListView(LoginRequiredMixin, generic.ListView):
model = Node
def get_queryset(self):
return Node.objects.filter(organisation__users__id=self.request.user.pk)
但是,我的意图是保持 DRY 并在单个点覆盖“主”query_set 方法,以便任何视图(例如表单下拉列表、API 端点)都将执行用户受限查询而无需额外代码。
例如,我使用 django 的通用列表视图有一个表单用于添加 Scan 对象,这需要用户选择 Scan 所属的节点。该表单当前显示来自其他组织的节点,这违反了我需要的权限逻辑。
不幸的是,被覆盖的 Node.objects 属性似乎没有任何效果,任何用户都可以看到所有节点。我是否采取了正确的方法?
【问题讨论】:
-
你试试这个
return super().get_queryset().filter(organisation__users_id=self.request.user.pk) -
这会导致错误:Related Field got invalid lookup: users_id
-
尝试将两个下划线改为
organisation__users__id -
@SergeyPugach:是的,它适用于在视图中定义的 query_set,但作为上面的 UserNodeManager 类的一部分仍然没有效果。
-
如何调用
get_queryset方法?您是否覆盖了所有管理器方法(即更新、获取、删除)?