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')
Related
Problem: I want to generate a random number, and ask the user to calculate the addition of these two. Then, I want to evaluate the number and see if the solution is correct.
My issue: I can do everything except the evaluation bit, as the values of the random numbers change!
HTML file:
<p> What is {{ a }} + {{ b }} ? </p>
<form action="{% url 'form_handle' %}" method="POST">{% csrf_token %}
{{form.as_p}}
<button type="submit">Submit</button>
</form>
FORM file:
class MyForm(forms.Form):
num1 = forms.CharField(max_length=20)
VIEW file:
def form_handle(request):
if request.method == 'POST':
form = MyForm(request.POST) # if post method then form will be validated
if form.is_valid():
cd = form.cleaned_data
num1 = cd.get('num1')
#num2 = cd.get('num2')
#result = cd.get('result')
if float(num1) == float(a + b):
# give HttpResponse only or render page you need to load on success
return HttpResponse("Good job!")
else:
# if sum not equal... then redirect to custom url/page
return HttpResponseRedirect('rr/') # mention redirect url in argument
else:
a = random.randrange(5,10);
b = random.randrange(10,20);
form = MyForm() # blank form object just to pass context if not post method
return render(request, "rr.html", {'form': form, 'a': a, 'b':b})
The error I get is "local variable 'a' referenced before assignment". I did try and change initialisation of a and b, and put the code right after the function declaration but that did not work either, as the function would compare the numbers (a + b) with another set of randomly generated numbers
Any help is much appreciated, or perhaps a new approach to this problem. Do note that I am a beginner in Python though
You can try to store a and b in session data:
def form_handle(request):
if request.method == 'POST':
form = MyForm(request.POST) # if post method then form will be validated
if form.is_valid():
cd = form.cleaned_data
num1 = cd.get('num1')
#num2 = cd.get('num2')
#result = cd.get('result')
a = request.session.get('a', 0)
b = request.session.get('b', 0)
if float(num1) == float(a + b):
# give HttpResponse only or render page you need to load on success
return HttpResponse("Good job!")
else:
# if sum not equal... then redirect to custom url/page
return HttpResponseRedirect('rr/') # mention redirect url in argument
else:
a = random.randrange(5,10);
b = random.randrange(10,20);
request.session['a'] = a
request.session['b'] = b
form = MyForm() # blank form object just to pass context if not post method
return render(request, "rr.html", {'form': form, 'a': a, 'b':b})
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)
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>
I'm having trouble with the POST section of the code below. I've come to the conclusion that after the form is sent from login the key variable is being reloaded and the integer change to no longer always match for the logic. But for some reason if i print riddle and dbanswer to the terminal, it always works.
I'm new to Python and Flask and am not sure if there's a way to fix this bug in my code by re-arranging it or using some sort of redirect to process the GET and POST separately so that the key is fixed between the two.
#app.route("/", methods=['GET','POST'])
def HomePage():
key = random.randint(1,3)
riddle = con.get("riddle:%i" %key)
dbanswer = con.get("riddle:%i:answer" %key)
# print(riddle)
# print(dbanswer)
if request.method == 'GET':
return render_template("login.html", riddle = riddle)
elif request.method =="POST":
answer = request.form['answer']
if answer == dbanswer:
return render_template("welcome.html")
else:
return render_template("login.html", riddle = riddle)
else:
return "<h2>Invalid request</h2>"
Just store the key in the form.
if request.method == 'GET':
return render_template('login.html', riddle=riddle, riddle_id=key)
Then in your login.html form, use that value:
<input type="hidden" name="riddle_id" value="{{ riddle_id }}"/>
Now when you POST that form to your view, you can grab it to complete the circle:
if request.method == "POST":
answer = request.form['answer']
riddle_id = request.form['riddle_id']
if answer == con.get("riddle:%i:answer" % riddle_id):
return render_template("welcome.html")
I have a django 1.6.11 form (views.py):
def posneg_nlp(request):
sys_project_name = request.GET.get('project', 'graph') # here oll is ok, it can get correct project value
success = False
monitoring_words = ''
pos_features = ''
neg_features = ''
date_saved = datetime(2015, 7, 29)
print('posneg_nlp form')
print("posneg_nlp request.GET.get('sys_project_name', 'graph')", request.GET.get('project', 'graph'))
if request.method == 'POST':
posnegnlp_form = PosnegnlpForm(request.POST)
if posnegnlp_form.is_valid():
print('posneg_nlp form is_valid')
success = True
sys_project_name = sys_project_name
# here it cannot get project value, it replaced with default:
print("posneg_nlp form is_valid request.GET.get('sys_project_name', 'graph')", request.GET.get('project', 'graph'))
print("sys_project_name ", sys_project_name)
monitoring_words = posnegnlp_form.cleaned_data['monitoring_words']
pos_features = posnegnlp_form.cleaned_data['pos_features']
neg_features = posnegnlp_form.cleaned_data['neg_features']
print('pos_features:', pos_features, 'neg_features:', neg_features)
posneg_nlp_filter(sys_project_name, pos_features, neg_features, db_collection=Vkwallpost)
#get_likes_wallposts_by_owner_id(typeobject='post', owner_id=None, item_id=None, filter_posts='likes')
else:
posnegnlp_form = PosnegnlpForm()
success = False
ctx = {'posnegnlp_form': posnegnlp_form, 'sys_project_name': sys_project_name, 'monitoring_words': monitoring_words,
'pos_features': pos_features, 'neg_features': neg_features, 'success': success}
return render_to_response('choose_nlp_filter.html', ctx, context_instance = RequestContext(request))
This is the second form among two. From first form i pass a variable sys_project_name to this form via template:
<div class="rowSubmit">
<a style="outline: medium none;" hidefocus="true" href="{{ DOMAIN_URL }}/post/choose_nlp_filter/?project={{ sys_project_name }}" class="btn btn-right"><span class="gradient">К шагу 2. Выбор фильтров </span></a>
</div>
When i print current value of sys_project_name in form function posneg_nlp(request) above it shows correct value request.GET.get('project', 'graph') equal to graph2 (happens on form render).
But after that after if posnegnlp_form.is_valid(): it stops to see it and request.GET.get('project', 'graph') shows value in case it not found, equal to "graph".
So, how to pass variable and dont allow to rewrite it?
In the first case, the view is responding to an http GET request, so request.GET contains your project parameter. When the form is submitted, now the view is responsing to an http POST request, and request.POST contains the form data. In the latter case, if you want request.GET to still contain the 'project' parameter, then you can pass it via the form action parameter in your form tag:
form action="/some/url/?project={{ sys_project_name }}"