Django “anonymous_required” decorator

Posted on Wednesday, January 6th, 2010 under , ,

I like Django’s login_required decorator. It’s a clean and simple way to allow and/or deny un-logged-in users to access parts of the website. But I also felt the need for a decorator to allow me to restrict access to some views only to non logged-in users. For instance, if an user in logged in, it should be denied access to views like /accounts/register or /accounts/login and redirected to his/her profile.

I’ve looked for one on the web, but couldn’t find anything suitable to my needs, so I’ve wrote my own:

from django.http import HttpResponseRedirect
 
def anonymous_required( view_function, redirect_to = None ):
    return AnonymousRequired( view_function, redirect_to )
 
class AnonymousRequired( object ):
    def __init__( self, view_function, redirect_to ):
        if redirect_to is None:
            from django.conf import settings
            redirect_to = settings.LOGIN_REDIRECT_URL
        self.view_function = view_function
        self.redirect_to = redirect_to
 
    def __call__( self, request, *args, **kwargs ):
        if request.user is not None and request.user.is_authenticated():
            return HttpResponseRedirect( self.redirect_to ) 
        return self.view_function( request, *args, **kwargs )

It’s also available on Django Snippets. Its usage is quite simple:

@anonymous_required
def my_view( request ):
    return render_to_response( 'my-view.html' )

That’s about it!

Related posts

8 Responses to “Django “anonymous_required” decorator”

  1. Praveen

    That what i was looking for.
    I tried your code but did not work
    Error:
    AttributeError at /accounts/login/

    ‘AnonymousRequired’ object has no attribute ‘__name__’

    Request Method: GET
    Request URL: http://localhost:8000/accounts/login/
    Exception Type: AttributeError
    Exception Value:

    ‘AnonymousRequired’ object has no attribute ‘__name__’

    Exception Location: C:\Python26\lib\functools.py in update_wrapper, line 33
    Python Executable: C:\Python26\python.exe
    Python Version: 2.6.0

  2. Tudor

    There was an “or” instead of an “and” (fixed now), but nothing that could generate that error.

  3. Praveen

    Still i am getting the same error.. here is my login view [I am using python2.6]

    @anonymous_required
    def login(request, form_class=None, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME):
    	"Displays the login form and handles the login action."
    	redirect_to = request.REQUEST.get(redirect_field_name, '')
     
            if request.method == "POST":
                form = AuthenticationForm(data=request.POST)
    	    if form.is_valid():
                    if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
                        redirect_to = settings.LOGIN_REDIRECT_URL
                    from django.contrib.auth.views import login
     
                    login(request, form.get_user())
                    if request.session.test_cookie_worked():
                        request.session.delete_test_cookie()
                    return HttpResponseRedirect(reverse('goto_dashboard'))
            else:
                form = AuthenticationForm(request)
    	    #captchform = form_class()
            request.session.set_test_cookie()
            if Site._meta.installed:
                current_site = Site.objects.get_current()
            else:
                current_site = RequestSite(request)
            return render_to_response(template_name, {
    	    'form': form,
            redirect_field_name: redirect_to,
            'site': current_site,
            'site_name': current_site.name,
        }, context_instance=RequestContext(request))
    login = never_cache(login)
  4. Tudor

    I think it might be conflicting with the “never_cache” decorator…

  5. Praveen

    Yeah.. many thanks.. The problem was with “never_cache” decorator..
    But i do not why we are disabling cache here.

    Regards
    Praveen

  6. Tudor

    Try it like:

    @anonymous_required
    @never_cache
    def login( ... )
  7. Praveen

    Thanks it works..
    I did not know before i thought both login = never_cache(login) and @never_cache works in same fashion.
    Really great post and it could give me more logic regarding decorator.
    Regards
    Praveen

  8. Tudor

    Read the python manual on decorators :)

Leave a Reply