如何在django guardian中获取用户具有特定权限的所有对象?
我现在正在对所有对象进行一个很笨拙的循环,但这样做会变得很慢:
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个查询,不过返回的结果中不会包含用户所在组有权限的对象。如果需要的话,你还可以指定一个权限的列表,而不仅仅是单个权限。在这里了解更多。