Django - user permissions to certain views?
Asked Answered
I

5

25

From the admin I see that you can allocate permissions to a user or a user group to :allow add, change or delete data from a model.

That is great, but I also need to allow a user or a user group to access or not a group of views. I have certain type of services on my web site so I want to allow some users to access a certain services (pages/views) but not others.

So how can I allow certain users/user groups access to certain views? Thank you!

Itinerary answered 4/1, 2011 at 19:11 Comment(0)
W
27

Users that cannot add or change etc. a certain model, will not be able to see it in the admin.

If we are talking about your custom created views then you could create something which checks a user for a permission and returns a 404 if they do not have that permission. Permissions are linked to models and a group can be assigned various permissions.

You can add a permission to a model like this:

# myproject/myapp/models.py

class MyModel(models.Model):
    class Meta:
        permissions = (
            ('permission_code', 'Friendly permission description'),
        )

Then you can check a if a user has permission like this:

@user_passes_test(lambda u: u.has_perm('myapp.permission_code'))
def some_view(request):
    # ...

Using permissions you can then easily add or remove them from users and groups simply using the admin interface.

Whisler answered 4/1, 2011 at 19:15 Comment(5)
Yes, I'm referring to the custom views I've created not the admin.Itinerary
Thank you. I'll give it a try. Looks relatively easy.Itinerary
@permission_required would be easier and more elegant hereFulgor
@Fulgor Sounds better yes. I answered this in Jan 2011: But I can't remember if the permission_required decorator was around then.Whisler
Make sure to migrate or syncdb to use them. I racked my brain trying to figure that out until I found this: docs.djangoproject.com/en/1.8/topics/auth/customizing/…Terricolous
S
10

You need to manage that manually, but it's pretty easy. Presumably there's an attribute that determines whether or not a group has permission to see a view: then you just decorate that view with either the permission_required decorator, if it's a simple question of whether the user has a particular Permission, or user_passes_test if it's a bit more complicated:

@user_passes_test(lambda u: u.is_allowed_to_see_view_myview())
def myview(request):
    ...etc...

assuming that is_allowed_to_see_view_myview is some sort of method on the User object.

The authentication docs are pretty comprehensive.

Singularity answered 4/1, 2011 at 19:23 Comment(0)
K
4

For class based views you can inherit UserPassesTestMixin class into the view and define test_func

from django.contrib.auth.mixins import UserPassesTestMixin

class MainView(UserPassesTestMixin, View):

    def test_func(self):
        return self.request.user.has_perm('app.get_main_view')

Take a look at this docs for more details on how to use this:

Kinsley answered 21/11, 2016 at 17:19 Comment(1)
Important information, it's quite recent django's feature (versions 1.9+)Holdback
A
4

If you are using Django 1.9+, you should be able to use PermissionRequiredMixin:

For example:

from django.contrib.auth.mixins import PermissionRequiredMixin

class MainView(PermissionRequiredMixin, View):
    permission_required = 'my_services.foo_bar'
    ...

This is basically a special case of UserPassesTestMixin, designed specifically to test whether the user has the indicated permission.

Alcove answered 25/7, 2019 at 21:1 Comment(0)
A
1

Permissions system is model-centric and assumes that permissions are tied to models. I think following 2 alternatives are best options:

A. If your views are related to some specific model, use custom permissions on that model as Marcus Whybrow suggested.

B. [not tested, might not work] Subclasss User and define your own permissions there. You don't need actual model, it's just wrapper for your app's custom permission:

from django.contrib.auth.models import User
class MyUser(User):
    class Meta:
        permissions = (('can_visit_$viewset1', 'Can visit $view_set_1'))

Don't forget to run syncdb to add custom permissions to database.

Amphora answered 5/1, 2011 at 1:10 Comment(1)
As of Django 1.3 there is no way to subclass User (apart from using AUTH_PROFILE_MODULE, but that doesn't help here).Eluvium

© 2022 - 2024 — McMap. All rights reserved.