tags:

views:

144

answers:

5

Hello there!

I need to check user authorization in every view of one of my Django apps (I don't use Django's built in auth system) and redirect user to a "login please" page, if authorization has failed.

Code looks like this:

try:
    admin_from_session = request.session['admin'];
    admin = Administrator.objects.get(login = admin_from_session.login, password = admin_from_session.password, enabled=True);
except KeyError, Administrator.DoesNotExist:
    return HttpResponseRedirect('/controlpanel/login')

Question is: how can I run this code at the beginning of every view, without repeating it every time?

If I would write my program on PHP, i would put this code in separate file and write something like this at the beginning of every page that requires authorization:

include("redirect_if_not_logged_in.inc.php");

The solutions I found was:

  • inclusion tags - doesn't do, because I can't redirect anywhere from there
  • custom function - also doesn't do, because of the same reason.

The task seems trivial, but I can't find a solution. I would be very grateful for any help.

+1  A: 

Function decorators comes to mind

bugspy.net
may be you mean something else? Function annotations in python is a completely unrelated feature: http://www.python.org/dev/peps/pep-3107/
SilentGhost
Decorators. Sorry
bugspy.net
+2  A: 

Middleware.

Ignacio Vazquez-Abrams
+1: Middleware rules. Earlier this week I learned how to add content-length headers with middleware.
S.Lott
Yeah middleware is something to look in to, but one word answers don't help much.
Derek Reynolds
+4  A: 

Look at the source code for django.contrib.auth decorators. They do exactly what you want, but for the built-in Django authentication system (see the documentation). It shouldn't be hard to do something similar for your authentication system.

BTW, why don't you use the built-in auth? You can use it with custom authentication backends...

Ludwik Trammer
Thank you for your help. I don't use built in auth because mine requires many custom fields and functionality and I don't really know, how to make built in auth work as I need. Perhaps I'm too used to rewriting all the things on my own, rather then using other people's code. Guess it's a bad habit :)
Silver Light
Using a custom authentication backend you can use any number of fields. You just write a class that implements two methods:1. authenticate() - given login credentials (could be anything, doesn't have to be just login and password) it checks them, and returns user object from the database or None, appropriately.2. get_user() - given user id returns user object.That's all. django.contrib.auth will play nicely with other parts of django (like admin), and more importantly Django reusable apps (which are one of the strongest points of Django).
Ludwik Trammer
Documentation for writing custom authentication backends: http://docs.djangoproject.com/en/dev/topics/auth/#writing-an-authentication-backend
Ludwik Trammer
A: 

Take a look at the User authentication page here http://docs.djangoproject.com/en/dev/topics/auth/

Read on to "The login_required decorator".

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
   ...

You can setup where the user is to be redirected if not authenticated via the setting "settings.LOGIN_URL".

At the page there is also an example for a special authentication template you can style to anything you like!

initall
He is not using the built-in auth system, so `@login_required` won't work here.
Clément
A: 

I found the answer I was looking for. Function decorators allow to run a peace of code at the beginning of a function.

You must define a decorator function

def login_please_decorator(view_func):
    """
        Redirect if admin was not logged in
    """
    def _decorated(request, *args, **kwargs):
        #Check authorization
        try:
            admin_from_session = request.session['admin'];
            admin = Administrator.objects.get(login = admin_from_session.login, password = admin_from_session.password, enabled=True);
            return view_func(request,*args, **kwargs);
        except KeyError, Administrator.DoesNotExist:
            return HttpResponseRedirect('/cp/login?ret=' + request.path);

return _decorated 

And decorate a view using this function name:

@login_please_decorator
def some view(request):   
    # do something ...
    # ...

Ludwik Trammer, bugspy.net, thank you for your help.

Silver Light