On the html page
{{ item.filename }}
On the flask routing code :
#app.route("/<username>/<filename>")
def downloadimage(username, filename):
However, this isn't routing the routing method.
What's the issue here ?
You can use the url_for method here.
Use it like this:
{{ item.filename }}
Here, downloadimage is the name of the function added to the required URL, username and filename are the parameters that should be passed to the function.
Related
I have a route defined like this:
#app.route('/magic/<filename>')
def moremagic(filename):
pass
And now in a template I want to call that route using url_for() like so:
<h1>you uploaded {{ name }}<h1>
Click to see magic happen
I have tried:
Click to see magic happen
That throws a jinja2.TemplateSyntaxError: expected token ':' got }
Can anyone suggest how to get the {{ name }} that appears in the template into the url_for() so that when I click I call the correct app.route?
Everything inside the {{ ... }} is a Python-like expression. You don't need to use another {{ ... }} inside that to reference variables.
Drop the extra brackets:
<h1>you uploaded {{ name }}<h1>
Click to see magic happen
(Note that the url_for() function takes the endpoint name, not a URL path; the name defaults to the name of the function, moremagic in your example).
I want to pass an endpoint to url_for where the endpoint contains name=value parameters where the name is a variable.
Basically i have multiple templates which could be collapsed down to one template if I could pass parameter variable names. A solution could be to pass a dictionary, but there may be other ways. I could definitely do it by post-processing the html jinja generates before it gets rendered.
I have tried all the obvious tricks I can think of including nested {{ }}.
So at the end of my route code I have
# routes.py
...
#bp.route('/customer/add/prompt/<customer_id>',methods = ['POST', 'GET'])
#login_required
def customer_add_prompt(customer_id):
#code code code
return render_template('customer_add.html',
customer_id = customer_id)
Indeed I have lots of routes for different subjects (customer, product, invoice) that all end this way. So for each subject I need a jinja template that looks like this.
# customer_add.html
...
<form action = "{{ url_for(customer_add, customer_id = customer_id) }}" method = "POST">
<-- html htlm htlm -->
</form>
When the user submits the form the endpoint for customer_add is followed and customer_add expects and is passed customer_id = 1234 (or whatever the value is).
Here is the problem. I should be able to combine all the templates like so.
# subject_add.html
...
<form action = "{{ url_for(subject_target, subject = subject_id) }}" method = "POST">
<-- html htlm htlm -->
</form>
Then render it like so.
# routes.py
...
#bp.route('/customer/add/<customer_id>',methods = ['POST', 'GET'])
#login_required
def customer_add_prompt(customer_id):
#code code code
subject_target = 'customer_add.html'
subject = 'customer_id'
subject_id = customer_id
return render_template(subject_target,
subject = subject_id)
When I do this I get an error saying Could not build url for endpoint 'customer_add' with values ['subject']. Did you forget to specify values ['entity_id']?
Testing shows that subject_target and subject_id get substituted for fine. But subject is not substituted for because in the url_for syntax it is a parameter name and the endpoint is expecting a value for a variable named customer_id not subject.
I am hoping there is a way to say what the parameter name will be in jinja. Generalising I may want to pass a dictionary of parameters.
Ideally I could pass d = {'subject': x, ...} like this url_for(subject_action, d) and Jinja would regard this as equivalent to url_for(subject_action, subject=1234, ... when x=1234.
You can add arguments to url_for(). As per the docs:
Variable arguments that are unknown to the target endpoint are
appended to the generated URL as query arguments
so you can do
<form action = "{{ url_for(action_target,
subject_type=subject_id,
2nd_variable=2nd_variable,
etc...) }}" method = "POST">
But as wonka said you'd probably be better off sending data as POST params.
If I misunderstood and your trying to pass data from your render_template call in your view then you can do that too.
return render_template('template_name.html',
data={
"action_type": "action",
"subject_type": subject_value
})
which you can then access in your template using {{data["subject_type"]}}
The answer turns out to be obvious. Instead of evaluating url_for in the template using jinja, evaluate it in the route and pass the result to jinja via render_template.
I'm pretty new to flask any web development in general. So I was wondering how you generate a link. as in, when somene registers on your website you create a link like site.com/leak1953 and that would be their profile.
For generating links there exists the function flask.url_for() which generates a URL given the endpoint with a method provided. You can use this function also in JINJA2 templates. To provide an external link use
{{ url_for('index.main', _external=True) }}
If you want to include parameters to the url just add them to the url_for parameters.
{{ url_for(show_user_profile, username='Klaus') }}
Variable Rules
To add variable parts to a URL you can mark these special sections as . Such a part is then passed as a keyword argument to your function. Optionally a converter can be used by specifying a rule with <converter:variable_name>.
#app.route('/user/<username>')
def show_user_profile(username):
# show the user profile for that user
return 'User %s' % username
#app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return 'Post %d' % post_id
source: http://flask.pocoo.org/docs/0.12/quickstart/#variable-rules
I am having a flask url_for('') error in a very simple application.
from flask import Blueprint, render_template, abort
from jinja2 import TemplateNotFound
base = Blueprint('main', __name__)
#base.route('/', defaults={'page':'home'})
#base.route('/<page>')
def show(page):
try:
return render_template('%s.html'%page, name='my name is')
except TemplateNotFound:
abort(404)
the above is my blueprints file, those routes work fine but if I try to do
with flask.test_request_context():
print url_for('home') #home.html or any other forms
I just get this error:
raise BuildError(endpoint, values, method)
werkzeug.routing.BuildError: ('home', {}, None)
can anyone help me figure out what's going on here?
in my html page I can print out the location of static files with:
{{ url_for('static', filename='style.css') }}
but if i try to do:
{{ url_for('home') }}
Again I get the same error. Anyone have some advise as how to proceed?
You're trying to use url_for the wrong way round, I think.
url_for in general maps an endpoint, i.e. a python function/method, to an url. In your case home is the value of a parameter, not an endpoint.
So, instead, use the name of the python function you want the url for:
url_for('show', page='home')
Should be what you're looking for.
When you do {{ url_for('home') }} it doesn't return route of home.html instead it returns the route of a function home, which by the way doesn't exist.
So to fix your problem,
The proper way of using url_for is :
{{ url_for('show') }}
If I'm making a blog site and I want to set up routing such that
#app.route('/<username>/<postname>', methods=['GET'])
routes to the post with name 'postname' of the user with name 'username', how do I get the html to recognize this? I've been trying to do something like
<a href={{ url_for('/', username=user.name, postname=post.name) }}>{{post.name}}</a>
I'm also trying to reconcile this with Flask understanding special keywords /login or /about so that it checks if the user is trying to access those first. How can I implement those checks?
The first argument to url_for in your template should be the name of the view function you decorated:
#app.route('/<username>/<postname>', methods=['GET'])
def view_user_post(username, postname):
^^^^^^^^^^^^^^
Now, you can write this in your template:
{{ url_for('view_user_post', username=user.name, postname=post.name) }}
This lets you change the URL in the route without having to update it elsewhere in your codebase.