如何在django guardian中获取用户具有特定权限的所有对象?

3 投票
3 回答
4848 浏览
提问于 2025-04-16 09:48

我现在正在对所有对象进行一个很笨拙的循环,但这样做会变得很慢:

videos = Video.objects.all()
video_list = []
for video in videos:
    checker = ObjectPermissionChecker(request.user)
    if checker.has_perm('view_video', video):
        video_list.append(video)

我想应该有办法直接获取这个用户有权限的所有对象。

3 个回答

1

如果你想大幅提高速度,为什么不直接让数据库只提取你感兴趣的对象呢?

content_type = ContentType.objects.get_for_model(Video)
perm = Permissions.objects.get(codename='view_video'.split('.')[-1])

objs = set(
    UserObjectPermissions.objects.filter(user=user, permission=perm, content_type=content_type)
)

# and if you want to include groups
objs.update(
    set(
         GroupObjectPermissions.objects.filter(group__user=user, permission=perm, content_type=content_type)
    )
)

这样做可以获取到用户有权限访问的所有用户对象,这些权限是通过他们的个人用户和所属的组来决定的。

1

你知道在每次循环中你都在创建一个新的 ObjectPermissionChecker 实例,其实你并不需要这样做。我建议你可以尝试一些更简洁的写法,这样可能会让代码更好看,也可能会提高运行速度。

checker = ObjectPermissionChecker(request.user)

videos = Video.objects.all()

video_list = [video for video in videos if checker.has_perm('view_video', video)]

关于你的问题,你可以使用 django-object-permissions,想了解更多使用方法可以查看 这里

10

几天前,更新了一个新的快捷功能,叫做“get_objects_for_user”。如果你使用的是旧版本的guardian,无法更新的话,可以直接复制那里的代码。

from guardian.shortcuts import get_objects_for_user
...
videos = get_objects_for_user(request.user, "view_video", Video.objects.all())

这个功能总是会执行3个查询。如果你把“use_groups”这个参数设为False,那么就只会执行2个查询,不过返回的结果中不会包含用户所在组有权限的对象。如果需要的话,你还可以指定一个权限的列表,而不仅仅是单个权限。在这里了解更多

撰写回答