0

In django, I want to do a particular action just before login_required() is called for a view. One hack or easy way out is to just have that url point to a view where login is not required and do that particular action (action: setting some things in the request.session) and then redirect back to this main view where login is required.

How should I go about it, if there's some option to cater to such things in django?

Is there a better or simpler way than to write my own decorator to do this?

zubinmehta
  • 4,368
  • 7
  • 33
  • 51
  • 1
    Your hack would not guarantee your action is performed; users who know the URL of the view with `login_required` could easily bypass the other view. Unfortunately, I don't know a solution to your problem. – Jesse Webb Dec 28 '11 at 22:03

4 Answers4

2

Decorator is the best way, because it make code easy to understand and as for security reason, user can block redirections so you'll need to think about how to avoid this.

This arcticle seems usefull How to make a chain of function decorators?, because I think you'll need to pass request variable and also place your decorator to process checking first.

Community
  • 1
  • 1
Dracontis
  • 4,184
  • 8
  • 35
  • 50
1

Writing your own decorator is the best way to approach this. Anywhere that you have @login_required, just add your own decorator in addition to the login_required decorator.

Or, you could call the login_required function from your decorator.

Jordan
  • 31,971
  • 6
  • 56
  • 67
  • No need to replace Django decorator, just add own decorator in right place, they will be called one after another. – demalexx Dec 29 '11 at 10:28
  • I wasn't clear. I meant to say that you add both, so I'll edit my answer to make it more clear. – Jordan Dec 29 '11 at 19:09
1

Just use the user_passes_test decorator instead and do your custom stuff before manually validating that they are authenticated. See: https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.user_passes_test

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • +1: The `login_required` decorator actually uses `user_passes_test` internally, so this would probably work. I still think middleware's the right approach though, based on the OP's example. – elo80ka Dec 29 '11 at 06:13
  • Middleware is mostly likely taking a bazooka to a knife fight. `user_passes_test` will simply replace the `login_required` decorator he's already using and allow him access to the session to add whatever extra variables are required. – Chris Pratt Dec 29 '11 at 15:12
1

Your question doesn't give much detail, but going by your example (setting some request variables), it sounds like you need Request Middleware. Take a look at the builtin django.contrib.auth.middleware.AuthenticationMiddleware for an example:

class AuthenticationMiddleware(object):
    def process_request(self, request):
        assert hasattr(request, 'session'), "The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."

        request.user = SimpleLazyObject(lambda: get_user(request))

You'll need to define a class with the process_request method (as shown above). The process_request method will be called for each request, and passed a request instance. Within the method, you can check for request.user, and if the user is authenticated, and set whatever variables you want for the current request.

elo80ka
  • 14,837
  • 3
  • 36
  • 43