Django: Applying permissions in the URL dispatcher?
Asked Answered
S

4

11

In my Django application, I have certain permissions which users need in order to access certain views (using django.contrib.auth). This works fine, using the @permission_required decorator on my view functions.

However, some of my URLs resolve to views which I did not write, such as the built-in django.contrib.auth.views.password_change, as in the following urls.py:

urlpatterns = patterns(
 (r'^$', "users.views.index"),
 (r'^password_change/$', 'django.contrib.auth.views.password_change'))

In this instance, I have nowhere to apply my @permission_required decorator -- or do I? Is there any way to apply a permissions restriction at the URL dispatcher level?

Steep answered 11/8, 2010 at 17:39 Comment(0)
M
10

It's possible to import the login required function and apply it to the generic view:

from django.contrib.auth.decorators import login_required
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
    (r'^foo/$', login_required(direct_to_template), {'template': 'foo_index.html'}),
    )

as mention here.

Mimi answered 11/8, 2010 at 17:47 Comment(5)
How would you use permission_required in the same way? Specifically how would you pass it the permission name argument?Tantalite
@Manoj: check out this section of the documentation: docs.djangoproject.com/en/dev/topics/auth/… the idea is to write a thin wrapper (with permission_required decorator) around the generic view, and point your urlconf to that wrapper...Mimi
That is what I did in my answer. Just wanted to know if there was any other way to go about it. Thanks.Tantalite
I need a customized decorator, how can I create a customized permission check function to wrap the view function, thanks.Infectious
@stallman just write your own decorator, import it, and use it in place of login_required. A decorators really is just a function, and can be used like one...Mimi
V
18

A decorator is a fancy word for a function that wraps another function. login_required is a wrapper function for a view while permission_required constructs a wrapper for your view. In other words, login_required is itself a decorator and permission_required(perm) constructs a decorator.

from django.conf.urls import url
from django.contrib.auth.decorators import login_required, permission_required

urlpatterns = [
    url(r'^public/', myview),

    url(r'^users_only/', 
        login_required(myview)),

    url(r'^users_with_perms/',
        permission_required('myapp.view_mymodel', login_url='login')(myview)),

    url(r'^login_page/', myloginview, name='login'),
]
Vesta answered 15/7, 2015 at 7:51 Comment(1)
you are the best! This answer is more intelligible the the chosen oneMeanly
M
10

It's possible to import the login required function and apply it to the generic view:

from django.contrib.auth.decorators import login_required
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
    (r'^foo/$', login_required(direct_to_template), {'template': 'foo_index.html'}),
    )

as mention here.

Mimi answered 11/8, 2010 at 17:47 Comment(5)
How would you use permission_required in the same way? Specifically how would you pass it the permission name argument?Tantalite
@Manoj: check out this section of the documentation: docs.djangoproject.com/en/dev/topics/auth/… the idea is to write a thin wrapper (with permission_required decorator) around the generic view, and point your urlconf to that wrapper...Mimi
That is what I did in my answer. Just wanted to know if there was any other way to go about it. Thanks.Tantalite
I need a customized decorator, how can I create a customized permission check function to wrap the view function, thanks.Infectious
@stallman just write your own decorator, import it, and use it in place of login_required. A decorators really is just a function, and can be used like one...Mimi
T
-1

One approach would be to wrap the views you did not write.

from django.contrib.auth.views import password_change

@permission_required('my_perm')
def wrapper(*args, **kwargs):
    return password_change(*args, **kwargs)

#URLs
urlpatterns = patterns(
  (r'^$', "users.views.index"),
  (r'^password_change/$', 'wrapper'))
Tantalite answered 11/8, 2010 at 17:54 Comment(0)
H
-2

I have a little hack about the Django URL resolver, you may apply a decorator at URL dispatch level:

from django_url_decr import url_decr
from django.contrib.auth.decorators import login_required

urlpatterns = patterns(''
                       url_decr(r'^users/',
                                include('users.urls'),
                                decr=login_required))
Howardhowarth answered 2/11, 2014 at 9:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.