views:

446

answers:

4

I can't figure out why the permission required decorator isn't working. I would like to allow access to a view only for staff members. I have tried

@permission_required('request.user.is_staff',login_url="../admin")
def series_info(request):
  ...

and also

@permission_required('user.is_staff',login_url="../admin")
def series_info(request):
  ...

As the superuser, I can access the view, but any users I create as staff can't access it and are redirected to the login url page. I tested the login_required decorator and that works fine.

+3  A: 

permission_required() must be passed a permission name, not a Python expression in a string. Try this instead:

from contrib.auth.decorators import user_passes_test
def staff_required(login_url=None):
    return user_passes_test(lambda u: u.is_staff, login_url=login_url)

@staff_required(login_url="../admin")
def series_info(request)
...


Thanks. That does work. Do you have an example of how to use permission_required? From the documentation docs.djangoproject.com/en/1.0/… and djangobook.com/en/2.0/chapter14 I thought what I had should work.

Re-read the links you posted; permission_required() will test if a user has been granted a particular permission. It does not test attributes of the user object.

From http://www.djangobook.com/en/2.0/chapter14/:

def vote(request):
    if request.user.is_authenticated() and request.user.has_perm('polls.can_vote')):
        # vote here
    else:
        return HttpResponse("You can't vote in this poll.")

   #
   #
 # # #
  ###
   #

def user_can_vote(user):
    return user.is_authenticated() and user.has_perm("polls.can_vote")

@user_passes_test(user_can_vote, login_url="/login/")
def vote(request):
    # vote here

   #
   #
 # # #
  ###
   #

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote', login_url="/login/")
def vote(request):
    # vote here
John Millikin
Thanks. That does work. Do you have an example of how to use permission_required? From the documentation http://docs.djangoproject.com/en/1.0/topics/auth/#the-permission-required-decorator and http://www.djangobook.com/en/2.0/chapter14/ I thought what I had should work.
Mitch
Ah. I see. Thanks for persevering.
Mitch
+1  A: 

Try this:

@permission_required('is_staff', login_url = "../admin")
def series_info(request):
    # stuff.
Manoj Govindan
Thanks but that didn't work either.
Mitch
A: 

Here is an example of behavior I don't understand. I create a user, request and decorate a test function with permission_required checking for 'is_staff'. If the user is superuser, then access is granted to the test function. If the user only has is_staff = True, access is not granted.

from django.http import HttpRequest
from django.contrib.auth.models import User
from django.contrib.auth.decorators import permission_required

@permission_required('is_staff')
def test(dummy='dummy'):
    print 'In test'

mb_user = User.objects.create_user('mitch', '[email protected]', 'mbpassword')
mb_user.is_staff = True

req = HttpRequest()
req.user = mb_user

test(req) # access to test denied - redirected

req.user.is_staff = False

test(req) # same as when is_staff is True

req.user.is_superuser = True
test(req) # access to test allowed
Mitch
is_staff is an attribute of the user object, not a permission.
John Millikin
A: 

This is how I would do it:

from django.contrib.admin.views.decorators import staff_member_required

@staff_member_required
def series_info(request):
    ...

The documentation says about staff_member_required:

Decorator for views that checks that the user is logged in and is a staff member, displaying the login page if necessary.

wanson