Django: Staff Decorator

DjangoDecorator

Django Problem Overview


I'm trying to write a "staff only" decorator for Django, but I can't seem to get it to work:

def staff_only(error='Only staff may view this page.'):
    def _dec(view_func):
        def _view(request, *args, **kwargs):
            u = request.user
            if u.is_authenticated() and u.is_staff:
                return view_func(request, *args, **kwargs)
            messages.error(request, error)
            return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse('home')))
        _view.__name__ = view_func.__name__
        _view.__dict__ = view_func.__dict__
        _view.__doc__ = view_func.__doc__
        return _view
    return _dec

Trying to follow lead from here. I'm getting:

> 'WSGIRequest' object has no attribute '__name__'

But if I take those 3 lines out, I just get a useless "Internal Server Error". What am I doing wrong here?

Django Solutions


Solution 1 - Django

This decorator already exists as

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

@staff_member_required

Trunk: http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/views/decorators.py

Solution 2 - Django

For Class Based Views, you can decorate the view class's dispatch method like this:

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


@method_decorator(staff_member_required, name='dispatch')
class ExampleTemplateView(TemplateView):
    ...

Solution 3 - Django

This style of decorator function is used with a parameterised decorator - eg when you do:

@staffonly(my_arguments)
def function(request):
    blah

If you're not actually calling the outer function, ie you're using it like this:

@staffonly
def function(request):

You will get odd results, as the function object will be passed to the wrong one of the nested functions in the decorator.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmpenView Question on Stackoverflow
Solution 1 - DjangoMark LavinView Answer on Stackoverflow
Solution 2 - DjangoMark ChackerianView Answer on Stackoverflow
Solution 3 - DjangoDaniel RosemanView Answer on Stackoverflow