In my GET portion of the Flask function I'm working on I have some very simple code written in Python 3. The data I'm trying to pass in is never displayed on my HTML render.
#app.route("/sellselected", methods=["GET", "POST"])
#login_required
def sellselected(order_num):
if request.method == "POST":
#not done, just have a redirect to index
else:
stock_to_sell = db.execute("SELECT * FROM purchases WHERE order_num = :order_num", order_num=order_num)
#stock_to_sell = ['fish']
return render_template("sellselected.html", stock_to_sell=stock_to_sell, order_num=order_num)
The SQL statement seems to passing in nothing, it's just blank on the HTML render. But as a test I also used 'fish' and it's None/empty too.
Jinja looks like:
{% block main %}
<list>
<ul>{{ stock_to_sell }}</ul>
<ul>{{ order_num }}</ul>
</list>
{% endblock %}
So the body of the page has the order number, but stock_to_sell is always empty.
Your problem is not related to jinja anymore. Your route is wrong, it should be: #app.route("/sellselected/<order_num>", methods=["GET", "POST"]).
Because you pass order_num to sellselected function so you need to declare it on route.
You say you like to pass the param order_num as GET right? Because the code say POST is redirect to index.
So, you pass the param as GET. You need to get it first
current_order = request.args.get('order_num')
Your code should be:
#app.route("/sellselected", methods=["GET", "POST"])
#login_required
def sellselected(order_num):
if request.method == "POST":
# not done, just have a redirect to index
else:
order_num = request.args.get('order_num')
stock_to_sell = db.execute("SELECT * FROM purchases WHERE order_num = :order_num", order_num=order_num)
return render_template("sellselected.html", stock_to_sell=stock_to_sell, order_num=order_num)
Beware if you iterate over an object then it's contents will comeback empty. This is because the result is a generator, and it's values can be accessed only once.
Won't work as gcp_certs has been iterated over:
gcp_certs = connection.execute(query)
for cert in gcp_certs:
print(cert.name)
return render_template('certifications.html',
gcpcerts=gcp_certs,
now=datetime.utcnow(),
cookie=token)
Works:
gcp_certs = connection.execute(query)
return render_template('certifications.html',
gcpcerts=gcp_certs,
now=datetime.utcnow(),
cookie=token)
One solution:
imports copy
gcp_certs = list(connection.execute(query))
sql_select = ''
for cert in copy.copy(gcp_certs):
print(cert.name)
return render_template('certifications.html',
gcpcerts=gcp_certs,
now=datetime.utcnow(),
cookie=token)
Related
There is a drop-down list of items. If send button is pressed, the elements of the object are handled and I get a certain result. I want to check if the object is empty, then redirect to another page?
The code:
html:
<form action = "" method = "POST" enctype = "multipart / form-data">
<select id = 'sel' name = 'sel' class = "selectpicker sel" multiple data-live-search = "true">
{% for elem in elements%}
<option id = "val" value = "{{elem}}"> {{elem}} </option>
{% endfor%}
</select>
<button> Send </button>
</form>
python:
# app.route ('/', methods = ['GET', 'POST'])
def index ():
if request.method == 'GET':
return render_template ('index.html', elements = elements) # get all the elements on the page
elif request.method == 'POST':
docs = request.form.getlist ('sel') # here I get the items selected from the list
result = handler.dosomething (docs) # handler function
return render_template ('handler.html', result = result)
else:
pass
How to check if docs is empty and there are no selected elements inside this variable, then when the button is pressed, redirect to another page, for example error.html?
You can add one more if statement. See below:
# app.route ('/', methods = ['GET', 'POST'])
def index ():
if request.method == 'GET':
return render_template ('index.html', elements = elements) # get all the elements on the page
elif request.method == 'POST':
docs = request.form.getlist ('sel')
if len(docs)>0:
result = handler.dosomething (docs)
return render_template('handler.html', result = result)
else:
return render_template('error.html')
I am working on a blog application in Flask and have been struggling to find a way to wrap up some code that will filter blog posts by categorical attributes (or tags) that users will add to their posts. For example, the code below is meant to return all posts that have been marked as 'anonymous'.
#app.route('/search', methods=['GET', 'POST'])
def search():
form = SearchForm()
if form.validate_on_submit():
anonymous = form.anonymous.data
flash('Here are your search results!')
return redirect(url_for('search_results', anonymous=anonymous))
return render_template('search.html', title='Search', form=form)
#app.route('/search_results/', methods=['GET', 'POST'])
def search_results():
page = request.args.get('page', 1, type=int)
anonymous = request.args.get('anonymous')
posts = Post.query.filter_by(anonymous=anonymous).paginate(page, app.config['POSTS_PER_PAGE'], False).items
return render_template('search_results.html', title='Search Results', posts=posts)
As the code above shows, I would like to be able to use request.args.get('anonymous') to retrieve whether the user is searching for anonymous posts and then use Post.query.filter_by(anonymous=anonymous) to find all posts that match this description. This works without a problem when I use Post.query.filter_by(anonymous=True), as you can see below.
print(Post.query.filter_by(anonymous=True))
posts = Post.query.filter_by(anonymous=True).paginate(page, app.config['POSTS_PER_PAGE'], False).items
print(posts)
SELECT post.id AS post_id, post.body AS post_body, post.image_name AS post_image_name, post.image AS post_image, post.anonymous AS post_anonymous, post.timestamp AS post_timestamp, post.user_id AS post_user_id
FROM post
WHERE post.anonymous = 1
[<Post my first post!>, <Post new post!>]
However, when I pass a variable to query.filter_by it does not appear to be inserting the value into the parameter. The result of the query is an empty set, even though the value of 'anonymous' is definitely set to True.
anonymous = request.args.get('anonymous')
print(anonymous)
print(Post.query.filter_by(anonymous=anonymous))
posts = Post.query.filter_by(anonymous=anonymous).paginate(page, app.config['POSTS_PER_PAGE'], False).items
print(posts)
True
SELECT post.id AS post_id, post.body AS post_body, post.image_name AS post_image_name, post.image AS post_image, post.anonymous AS post_anonymous, post.timestamp AS post_timestamp, post.user_id AS post_user_id
FROM post
WHERE post.anonymous = ?
[]
What I get in the query is the condition WHERE post.anonymous = ? instead of WHERE post.anonymous = 1 (or 0) which is what was hoping to see. Below is the code I have been trying:
My guess is that SQL-Alchemy simply does not support using a variable as a placeholder for the value I want to query with. Otherwise there may be some syntax that I am not aware of that I need to use to make this work, which is what I am looking into at this point. Any guidance would be much appreciated.
As discussed in the comments above the issue was that the value in anonymous was converted from a boolean to a string when it was passed from the search route to the search_results route. I used a quick if-else statement to convert the value back to boolean and everything works as expected now.
#app.route('/search', methods=['GET', 'POST'])
def search():
form = SearchForm()
if form.validate_on_submit():
anonymous = form.anonymous.data
print(anonymous)
print(type(anonymous))
flash('Here are your search results!')
return redirect(url_for('search_results', anonymous=anonymous))
return render_template('search.html', title='Search', form=form)
127.0.0.1 - - [18/Jun/2020 01:56:16] "GET /search HTTP/1.1" 200 -
True
<class 'bool'>
#app.route('/search_results/', methods=['GET', 'POST'])
def search_results():
page = request.args.get('page', 1, type=int)
anonymous = request.args.get('anonymous')
print(anonymous)
print(type(anonymous))
if anonymous == 'True':
anonymous = bool(1)
else:
anonymous = bool(0)
print(anonymous)
print(type(anonymous))
posts = Post.query.filter_by(anonymous=anonymous).paginate(page, app.config['POSTS_PER_PAGE'], False).items
print(posts)
return render_template('search_results.html', title='Search Results', posts=posts)
127.0.0.1 - - [18/Jun/2020 01:56:30] "POST /search HTTP/1.1" 302 -
True
<class 'str'>
1
<class 'bool'>
[<Post my first post!>, <Post new post!>]
i am trying to get nearby places using googleplaces with python and flask
i am getting this error: (UnboundLocalError: local variable 'place_name' referenced before assignment)
here is my code:
#app.route('/Search', methods=['POST', 'GET'])
#login_required
def Search():
if request.method == 'POST':
query_result = google_places.nearby_search(
lat_lng={'lat':31.7917, 'lng' : 7.0926},
radius=500,
types=[types.TYPE_SHOPPING_MALL] or [types.TYPE_STORE])`
if query_result.has_attributions:
print(query_result.html_attributions)
for place in query_result.places:
place.get_details()
place_name = place.name
print(place.name)
place_rating = place.rating
print(place.rating)
place_location = place.get_location
print(place.get_location)
for photo in place.photos:
photo.get(maxheight=500, maxwidth=500)
photo.mimetype
photo.url
photo.filename
photo.data
return render_template('Search.html', place_name, place_rating, place_location)
else:
return render_template('Search.html')```
#Note: i am new to python in general
return render_template('Search.html', place_name, place_rating, place_location)
The above isn't valid syntax. When you pass the details to the template, you need to do it as:
return render_template('Search.html', name = place_name,
rating = place_rating, location = place_location)
The variables name, rating and location will then be accessible in the template as {{name}}, {{rating}} and {{location}}.
However, the way you have the for loops laid out means the first time the return statement is reached, it will stop the loop and return the template with these variables.
Perhaps this is what you want, but you may wish to pass query_result to the template, and implement a Jinja2 for loop in the template to print out the various place details. You would remove the for loops and replace that whole block with:
return render_template('Search.html', all_places = query_result)
Then in the template something like:
{% if all_places %}
{% for place in all_places %}
<p><b>{{place.name}}</b> has a rating of <u>{{place.rating}}</u></p>
{% endfor %}
{% else %}
<p>No places found.</p>
{% endif %}
I'm trying to extend the flask-base project http://hack4impact.github.io/flask-base/templates/ . I have the following view functions:
#login_required
#main.route('/cities', methods=['GET', 'POST'])
def cities():
if request.method =='POST':
print(request.data)
redirect('/selected')
cities_list = []
recordset = Postings.query.all()
for r in recordset:
city = str(r.city)
elapsed_hours = round((time.time() - int(r.datetime)) / 3600, 1)
cities_list.append(str(r.city) + '-' + str(r.email) + '-' + str(elapsed_hours))
form = PostingSelectForm()
form.posting.choices = [(item, item) for item in cities_list]
return render_template("main/cities.html",
form = form)
#login_required
#main.route('/selected')
def selected():
return 'ddd'
I'm using a macro to generate a form as described in the docs above. The macro is called render_template and works normally to produce a form which I am able to submit. You can see the submitted info in the screenshot. However I am not able to capture the info in the lines:
print(request.data)
redirect('/selected')
and the redirect does not occur. When I look at the html of the wtf-form generated by the macro. it starts with;
<form action="" method="POST" enctype="" class="ui form
">
<div style="display:none;"><input id="csrf_token" name="csrf_token" type="hidden" value="1516882441##491001e55a57ceac4053b7937d21e61768f66d0b"></div>
So I'm wondering if the lack of an action is the problem here. I don't know what posting to "" does. Also if that is the problem how would I modify my form to include an action given that is generated by this macro. My forms code is:
class PostingSelectForm(Form):
posting = SelectField(
'posting',
choices=[('cpp', 'C++'), ('py', 'Python'), ('text', 'Plain Text')]
)
submit = SubmitField('Select')
I have multiple forms with one submit button for each of them, all in one template. render_template returns only empty StringFields. How can I render without touching my other StringFields?
#app.route('/', methods=['GET','POST'])
def index():
msform = msForm(request.form)
synform = synForm(request.form)
if request.method == 'POST' and msform.validate() and msform.ms_submit.data:
processed_text = model.most_similar(positive=[msform.ms_3.data, msform.ms_2.data], negative=[msform.ms_1.data])
msform.ms_submit.label.text = processed_text[0][0]
return render_template('my-form.html', msform=msform, synform=synform)
elif request.method == 'POST' and synform.validate() and synform.syn_submit:
processed_text = model.most_similar([synform.syn_1.data])
return render_template('my-form.html', msform=msform, synform=synform)
return render_template('my-form.html', msform=msform, synform=synform)
class msForm(Form):
ms_1 = StringField(label='Eingabe_1', default = 'king', validators=[validators.DataRequired(message='This Field is required')])
ms_2 = StringField(label='Eingabe_2', default = 'man', validators=[validators.DataRequired(message='This Field is required')])
ms_3 = StringField(label='Eingabe_3', default = 'queen', validators=[validators.DataRequired(message='This Field is required')])
ms_submit = InlineSubmitField(label = '?')
class synForm(Form):
syn_1 = StringField(label='Eingabe', default = 'king', validators=[validators.DataRequired()])
syn_submit = InlineSubmitField('?')
I am assuming you have two separate <form>s on your HTML page, like this for brevity:
<form>{{ msform }}</form>
<form>{{ synform }}</form>
I believe you are saying this: upon completing and submitting one form, the values are lost from the other. Is that correct?
If so, that's the expected behavior, not from Flask, but from your browser. When you submit an HTML <form>, only the data from that form tag is sent to the server. Therefor, any data in other <form> tags is lost.
To submit all forms, render all the forms in the same <form> tag. Give each form a prefix to ensure the input names don't collide.
msform = msForm(request.form, prefix='ms')
<form method="post">
{{ msform }}
{{ synform }}
</form>