Flask url_for producing wrong URL
Question:
The url_for generator in flask is not working for one of my views (it works for other views). The generator is giving /user/?name=Joe
while I expect /u/Joe
.
In the template I am trying to get the URL for the user page using: {{ url_for('user', name = g.user.name ) }}
This is the corresponding view function:
@app.route('/u/<name>')
@login_required
def user(name):
At first this was working but something changed. I have tried changing the view name and url with no luck.
Any thoughts? I am at a loss on this one…
The full app is available on GitHub: https://github.com/joehand/weight-and-more-tracker
Edit: The @login_required
decorated is the one provided by Flask-login.
Additionally, removing the <name>
variable does not solve the issue. The URL is then just /user
.
Answers:
did you ‘wrapped’ your function in login_required
decorator? In your case name
is supplied into url as a query string, not a flask view-function argument – maybe flask does not have a grip of the argument specification of your decorated user
view-function.
from the docs:
So let’s implement such a decorator. A decorator is a function that
returns a function. Pretty simple actually. The only thing you have to
keep in mind when implementing something like this is to update the
name, module and some other attributes of a function. This is often forgotten, but you don’t have to do that by hand, there is a
function for that that is used like a decorator (functools.wraps()
).
from functools import wraps
from flask import g, request, redirect, url_for
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
return redirect(url_for('login', next=request.url))
return f(*args, **kwargs)
return decorated_function
In api.py you are registering a view with the name ‘user’ that is probably conflicting with the method named ‘user’.
The url_for generator in flask is not working for one of my views (it works for other views). The generator is giving /user/?name=Joe
while I expect /u/Joe
.
In the template I am trying to get the URL for the user page using: {{ url_for('user', name = g.user.name ) }}
This is the corresponding view function:
@app.route('/u/<name>')
@login_required
def user(name):
At first this was working but something changed. I have tried changing the view name and url with no luck.
Any thoughts? I am at a loss on this one…
The full app is available on GitHub: https://github.com/joehand/weight-and-more-tracker
Edit: The @login_required
decorated is the one provided by Flask-login.
Additionally, removing the <name>
variable does not solve the issue. The URL is then just /user
.
did you ‘wrapped’ your function in login_required
decorator? In your case name
is supplied into url as a query string, not a flask view-function argument – maybe flask does not have a grip of the argument specification of your decorated user
view-function.
from the docs:
So let’s implement such a decorator. A decorator is a function that
returns a function. Pretty simple actually. The only thing you have to
keep in mind when implementing something like this is to update the
name, module and some other attributes of a function. This is often forgotten, but you don’t have to do that by hand, there is a
function for that that is used like a decorator (functools.wraps()
).from functools import wraps from flask import g, request, redirect, url_for def login_required(f): @wraps(f) def decorated_function(*args, **kwargs): if g.user is None: return redirect(url_for('login', next=request.url)) return f(*args, **kwargs) return decorated_function
In api.py you are registering a view with the name ‘user’ that is probably conflicting with the method named ‘user’.