I wanted to restrict access to views based on the users membership to group. I have used the @user_passes_test decorator testing to see if a user belongs to a group. However, to do this I have to create a function that filters for each group to later use in the decorator. This is because when the test function is within the decorator I cant pass a list with the groups that should get access. Is there another approach to this? Also how would this work in class based views?
Example of function used in decorator:
def op1_user(user):
if user.groups is None:
return False
return user.groups.filter(name="OP1").exists()
Hey there!
Can you explain a bit more about your need?
Do you need to filter for more than one group?
Do you need to filter for a specific group name, but don’t want to create a function to each one of it?
Actually, what I would say here is that this is entirely the wrong approach.
I would suggest that the “best Django process” is to use the built-in permission system rather than group level checks. It’s a lot more flexible and easier to administer.
Briefly, you define or identify a permission that is needed for each view, then assign that permission to all groups that need it. Then you use one of the permission tests to check to see if that user is allowed to access that view.
The concept is referred to as “Role-based security” and is a common pattern beyond Django. If you search through the forum, you can find other posts where this has been discussed in more detail.
Yes I think I have the same issues as those reflected in the thread. After reading this I have the following question, how can I attach the permissions to the users that are show in the django admin?(Where is the class definition in which under the meta tag I can add the necessary permissions)
If the permissions have to be added to some class that should be the user class used in the django admin(modify the meta of such class to contain the permissions). Is that the correct approach? As shown here Managing User Permissions in Django - Honeybadger Developer Blog.
Do your views not present Models to your users? Would maybe the permission fit to the most prominent on a view?
If not, you could create a “permission” app with one empty model that just holds permissions. This is something I have done in the past, although I would probably not do this again. But it works and you don’t have to think about how you programmatically add permissions that should be in your project by default.
Thanks I decided to follow this path since my views don’t correspond one to one with any models. My main objective is to restrict access to views more than restrict access to models. In this app I have created one permission to access each view. In that app I also create the permission groups.
My question is if the model has to be a empty model or if it should be an AbstractUser model? This is because in Customizing authentication in Django | Django documentation | Django under Substituting a custom User model it states this can be done to keep functionality but add permissions. I believe this could be my case.
Neither. The recommendation I made in the thread referenced above was to use the User model you are using in your project. (Either the system-default user or a custom user, whichever is the case.)
For possible clarification: A custom user model defined as class CustomUser(AbstractUser):
is not an “AbstractIUser model”. It’s a model that inherits from AbstractUser.
Thanks I decided to follow this path since my views don’t correspond one to one with any models. […]
My question is if the model has to be a empty model or if it should be an AbstractUser model? […]
I may just not understand the question right, … Are you referring to the path I described? If not, disregard what comes next. Otherwise, you don’t need a user model.
Here’s how it looks on my side. I have an app “permissions” with just a models.py (and the app.py).
permissions\models.py looks like this. What you see is the entire file.
from django.db import models
class Permissions(models.Model):
class Meta:
default_permissions = ()
permissions = (
("permission_name_1", "Human-readable permission description"),
("permission_name_2", "Human-readable permission description"),
... # Add permissions as needed
)
And then in the views you would just use the permission_required decorator.
Then in the admin UI you can assign users the permissions as needed.
Again, the above makes sense because I have certain permissions that don’t apply to a certain model or a specific app in my project. It may be up for debate if that’s a good thing, but for the use-case I have, this is a rather slim and simple solution.