Reputation: 4516
I have a custom permission model for my project and I'm not using django's default permissions backend. I have a custom has_permission template tag to check if the user has the specified permission or not.
The problem is that there's lots of queries done for the same checks every time, I'm looking for a way to reduce my Permission queries. What I'm doing inside my templates is like :
{% if user|has_permission:'jpermission.can_edit_jpermission' or
user|has_permission:'jgroup.can_edit_jgroup' or
user|has_permission:'role.can_edit_role' %}
and the code for has_permission template tag is as follows :
rep = perm_name.split('.') # rep is for e.g. "jpermission.can_edit_jpermission"
ctn_type = rep[0]
codename = rep[1]
pr = JPermission.objects.filter(model_name=ctn_type, codename=codename)
if pr.exists():
if user.has_perm(pr[0]):
return True
Specifically talking, the problem is that every time i check even for the exactly same if statements, lots of queries are made (from what I'm doing, it's obvious there will be).
Is there any other way i can go at it ? like query all permissions once, cache them, and do something like how prefetch_related is handled to prohibit further db queries (python filtering with loops and ... ) ?
P.S: has_perm
is also overridden and checks if users role
, group
or permissions
have the specified permission or not)
Upvotes: 3
Views: 638
Reputation: 39689
There are multiple solutions for this.
It looks like you are using django-guardian, and it is already caching the permissions:
Once checked for single object, permissions are stored and we don’t hit database again if another check is called for this object. This is great for templates, views or other request based checks (assuming we don’t have hundreds of permissions on a single object as we fetch all permissions for checked object).
Upvotes: 1