Optimizing Django ORM Access with a Filter

I applied a method in my django application that will check if the user has a specific permission or part of the group that contains that specific permission.

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

Now everything works like a charm, but the Django-Debug-Toolbar complains about the request that it duplicates many times, as a group to check.

This is a bottleneck for me, because some users will have 50 related groups, and I really don’t know how to optimize this query ...

Any suggestions?

thank

+4
source share
1 answer

, . ( - , ), 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
0

Source: https://habr.com/ru/post/1678094/


All Articles