I am trying to write a "login_required" decorator for the views in a WSGI+Werkzeug application.
In order to do this, I need to get at the user's session, which is accessible via the Request object that is passed into the view methods.
I can't figure out how to get at that instance of Request in the decorator, though. I looked at PEP318, specifically the fourth example, but I'm not quite getting it.
Here's what I'm trying:
def login_required(*args, **kw): def goto_login(**kw): return redirect(url_for('login')) def decorate(f): # args[0] should be request args[0].client_session['test'] = True logged_in = 0 if logged_in: return f else: return goto_login return decorate @login_required() @expose('/hello/<string:name>') def hello(request, name): return render_template('say_hello.html', name=name)
but I get an index out of bounds error trying to call args[0]
.
Is there any way I can get access to the request argument passed into the "hello" function in the "login_required" decorator?
To fix this, you need to change the repeat decorator so that it accepts an argument that specifies the number of times a function should execute like this: @repeat(5) def say(message): ... To define the repeat decorator, the repeat(5) should return the original decorator. The new repeat function returns a decorator.
Decorators are a prime-time example of a perfectly implemented feature. It does take a while to wrap your head around, but it's worth it. As you start using them, you'll notice how they don't overcomplicate things and make your code neat and snazzy.
Implementing Decorator Arguments You may expect that decorator arguments are somehow passed into the function along with this f argument, but sadly Python always passes the decorated function as a single argument to the decorator function.
Decorators in Python are very powerful which modify the behavior of a function without modifying it permanently. It basically wraps another function and since both functions are callable, it returns a callable. In hindsight, a decorator wraps a function and modifies its behavior.
The decorator login_required
is passed the function (hello
in this case).
So what you want to do is:
def login_required(f): # This function is what we "replace" hello with def wrapper(*args, **kw): args[0].client_session['test'] = True logged_in = 0 if logged_in: return f(*args, **kw) # Call hello else: return redirect(url_for('login')) return wrapper
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With