【问题标题】:Django ORM access optimization with Filter使用过滤器优化 Django ORM 访问
【发布时间】:2017-05-29 08:53:11
【问题描述】:

我在我的 django 应用上实现了一个方法,该方法将检查用户是否具有特定权限,或者它是否属于包含此特定权限的组。

def user_has_perm(user, *permissions_to_check):
        permission_check = True
        permissions_not_found = []

        user_groups = user.groups.all().prefetch_related('permissions')

        for permission in permissions_to_check:
            content_type, permission_codename = permission.split('.')
            if not user.has_perm(permission) and not user_groups.filter(
                    permissions__content_type__model__icontains=content_type,
                    permissions__codename__icontains=permission_codename).exists():  # Goes down from Groups to the single user permission
                permission_check = False
                permissions_not_found.append(permission)

        return permission_check, permissions_not_found

现在,一切都像一个魅力,但是,Django-Debug-Toolbar 它抱怨查询,它被重复多次作为要检查的组。

对我来说这是一个瓶颈,因为一些用户将关联 50 个组,我真的不知道如何优化这个查询...

有什么建议吗?

谢谢

【问题讨论】:

  • 权限检查可能很昂贵。在登录时检索用户的所有权限并将其缓存一段时间可能是个好主意。
  • 有一些不同的选择吗?
  • 真的这么难吗?

标签: python django orm


【解决方案1】:

正如 Klaus 所说,这是一个数据库杀手。如果有很多权限(即使没有您自己的任何应用程序,也会有很多),您可能会发现自己在 user_has_perm 函数中执行了数百个查询。你可以通过缓存来减少它

from django.core.cache import cache.

def user_has_perm(user, *permissions_to_check):
    hash = # create a hash from user.id and permissions_to_check.
           # maybe something as simple as "".join(permissions_to_check)

    perms = cache.get(hash)
    if perms: 
         return perms

    permission_check = True
    permissions_not_found = []

    user_groups = user.groups.all().prefetch_related('permissions')

    for permission in permissions_to_check:
        content_type, permission_codename = permission.split('.')
        if not user.has_perm(permission) and not user_groups.filter(
                permissions__content_type__model__icontains=content_type,
                permissions__codename__icontains=permission_codename).exists():  # Goes down from Groups to the single user permission
            permission_check = False
            permissions_not_found.append(permission)

    cache.set(hash, [permisson_check, permissions_not_found], 10**5)
    return permission_check, permissions_not_found

【讨论】:

  • 那么缓存时间呢?这是 5 分钟,如果我想将其设置为在用户注销时过期?
  • 超时参数是你可以控制的(第三个参数)
  • 你能建议我如何根据用户登录状态来控制它吗?
  • 查看编辑,但您真的应该查看此类文件的文档。
  • 这是一个奇怪的解决方案,也许更好的方法可以是:hash = "{0}{1}".format(request.session.session_key, permissions_to_check),其实就是session_key(如果我没记错的话),它会从登录、注销状态结束,反之亦然对吧?
猜你喜欢
  • 2021-03-02
  • 2021-10-01
  • 2022-01-08
  • 2014-09-24
  • 1970-01-01
  • 1970-01-01
  • 2022-06-12
  • 1970-01-01
  • 2011-04-17
相关资源
最近更新 更多