How to move variables from python to template and back? - python

I'm trying to get information from a form to my python file and then put into a template. Thing is, i know the form is working but i couldn't show it into the template.
Form here:
<div class="container" id="cont1">
<form action="http://127.0.0.1:5000/areas" method="POST" enctype="multipart/form-data">
<label for="author">Autor</label>
<input type="text" id="author" name="author"><br><br>
<label for="intro">Introdução</label>
<input type="text" id="intro" name="intro"><br><br>
<label for="content">Conteúdo</label>
<input type="text" id="content" name="content"><br><br>
<input type="file" id="planilha" name="planilha" accept=".csv"><br><br>
<input type="submit" value="Enviar">
</form>
</div>
then i try to get the data in app.py:
#app.route('/areas', methods=['GET', 'POST'])
def areas():
if request.method == "POST":
#app.context_processor
def f1():
aut = request.form.get['author']
intr = request.form['intro']
cont = request.form['content']
return dict(a=aut, i=intr, c=cont)
return render_template("areas.html")
else:
return render_template("areas.html")
I know it's working because i tried it out of the route and it showed what the form had. Now when i try into the route:
AssertionError
AssertionError: A setup function was called after the first request was handled. This usually indicates a bug in the application where a module was not imported and decorators or other functionality was called too late.
To fix this make sure to import all your view modules, database models and everything related at a central place before the application starts serving requests.
The decorator was the solution i found to get the data so i could place into templates like this:
<text>{{a}}</text>

The error is caused by the incorrect usage of the decorator. You don't need a decorator to pass variables to templates. render_template also accepts arguments which you can directly pass into your HTML file.
The following should work:
#app.route('/areas', methods=['GET', 'POST'])
def areas():
if request.method == "POST":
aut = request.form['author']
intr = request.form['intro']
cont = request.form['content']
return render_template("areas.html", a=aut, i=intr, c=cont)
else:
return render_template("areas.html")

Related

Flask Redirect is Duplicating POST request

I'm doing a simple shopping website with a order confirmation page but I'm finding that there are duplicate POST requests to my /confim-order route. I have a home page that redirects on POST:
#views.route('/', methods=['GET', 'POST'])
#login_required
def home():
if request.method == 'POST':
# save information from the form for later use
session['text'] = request.form.get('samples')
session['note'] = request.form.get('note')
return redirect(url_for('views.confirm_order'))
return render_template("home.html", user=current_user)
My order confirmation function:
#views.route('/confirm-order', methods=['GET', 'POST'])
#login_required
def confirm_order():
if request.method == 'POST':
text = session['text']
note = session['note']
session.pop('text', None)
session.pop('note', None)
create_order(current_user, text, note)
return redirect(url_for('views.home'))
elif request.method == 'GET':
text = session['text']
note = session['note']
sample_list = get_samples(text, note)
return render_template("confirm.html", user=current_user, sample_list=sample_list)
There's no JavaScript in the HTML template. What's in confirm.html is essentially:
<form method="POST">
<div class="form-group">
<label for="cc">Credit Card</label>
<input type="text" class="form-control" id="cc" name="cc" placeholder="Credit Card Number" />
</div>
Click button to place order:
<p></p>
<div align="right">
<button type="submit" id="submit_btn" class="btn btn-success">Place Order</button>
</div>
</form>
This is what I see: sometimes, clicking submit works fine. Most times clicking submit results in two POST requests to confirm_order() and then I get a "This site can’t be reached" message in my browser at http://localhost:5000/confirm-order. I've been at this for almost an entire day. I put some print statements that seem to suggest the first POST to /confirm-order is initiated correctly from the template rendered we reach /confirm-order by GET from home: /. The second POST to /confirm-order came immediately after first the POST from within POST of /confirm-order. When that happens, I get the "This site can't be reached" message and I find that duplicate orders have been created.
I've searched online and most people that have duplicate POST issues are using JavaScript along with the form submission button. But my page doesn't use Javascript. If someone sees what's wrong, any help is greatly appreciated. Thank you.
EDIT: Here's the create_order() function in case something in there is causing the problem:
def create_order(user, text, note):
new_order = Order(user_id=current_user.id, text=text,
status='submitted', note=note)
db.session.add(new_order)
db.session.commit()
I'm not 100% sure this is the issue but it's the most likely thing I can think of.
I think there are some issues in your html since you don't specify the url for action. I would also use an input tag rather than button for submit.
More generally, I would also recommend following a few of the things mentioned here. So use the data in request.form rather than in the session object since you can control and validate that more explicitly within Flask (for instance if this is going into production you may want to implement WTF Forms for security reasons to prevent CSRF).
<form action="/confirm-order" method="post">
<div class="form-group">
<label for="po">Purchase Order</label>
<div class="form-group">
<label for="cc">Credit Card</label>
<input type="text" class="form-control" id="cc" name="cc" placeholder="Credit Card Number" />
</div>
Click button to place order:
<p></p>
<div align="right">
<input type="submit" id="submit_btn" class="btn btn-success">Place Order</input>
</div>
</form>

How to pass the value to html input by add optional parameters to the link of the website to turn it into an API (flask)

I'm new to flask and I wonder how to pass the value to the HTML by adding optional parameters into the link
Example HTML:
<HTML>
<body>
<form method=post enctype=multipart/form-data>
<input type=text name=link>
<input type=submit value=Open>
</form>
</body>
</HTML>
Code I'm using to call the HTML above:
#app.route('/link', methods=['GET', 'POST'])
def open_link():
if request.method == "POST":
if 'link' != '':
text = request.form['link']
webbrowser.open(text)
return render_template("get_link.html")
Now, I want to add a parameter to the link to automatically pass the value for the input in, so that I can make it into an API
Example
http://192.168.5.107:8000/link/**add_para_here = hi**
Any suggestion? and only sorry for my bad English.Thank you
If I understand you correctly, you would like to use optional url parameters within your request. So that the url can be created in the following way.
http://127.0.0.1:8000/link?param0=value0&param1=1
In this case the form would look like this.
<form action="{{ url_for('link', param0='value1', param1=1) }}" method="post">
<input type="text" name="link">
<input type="submit" value="Open">
</form>
Within the endpoint, the parameters can be queried via request.args. Default values and an optional type conversion can also be specified here.
#app.route('/link', methods=['GET', 'POST'])
def open_link():
param0 = request.args.get('param0')
param1 = request.args.get('param1', 0, type=int)
if request.method == "POST":
if 'link' != '':
text = request.form['link']
# ...
return render_template("get_link.html")
Have fun implementing your project.

how to delete an object in django [duplicate]

i want to delete a task from the database so i use this code
this is my delete view
def task_Delete(request,id=None):
if request.method == 'POST':
form = TaskForm()
id = int(request.POST.get('task.id'))
task = Task.objects.get(id=id)
task.delete()
messages.success(request,"successfully delete")
return render_to_response('home.html', {'form': form})
and that is my urls.py
url(r'^task_Delete/$', views.task_Delete, name='task_Delete')
this the code of the button delete :
<form action="{% url 'task_Delete' %}" method="post" >
{% csrf_token %}
<input type="hidden" name="task_id" value="{{task.id}}" />
<input type="submit" value="delete task">
</form></td>
</tr>
when i click on delete nothing happend i don't know why , please help thanks in advance
There are various problems in your code (for example the TaskForm is not needed at all) however if you change the line
id = int(request.POST.get('task.id'))
to
id = int(request.POST.get('task_id'))
the object will probably be deleted; remember that the request parameter's name will be the same as the name of the input (task_id). I recommend using proper CBVs (a DeleteView) for what you want to do - if you want a slow and comprehensive tutorial on that I recommend this article: https://spapas.github.io/2018/03/19/comprehensive-django-cbv-guide/

Flask - User input and Buttons with back-end actions, returning text to user

I'm running a small Flask test and attempting to do the following:
I have two forms.
The first - receives users input, then has a submit button. When the submit button is pressed I would like to 1.) execute a back-end Python program using the two values from 'doritos' and 'oreos' then 2.) return some relative text back to the user (i.e., successful) on the same page, next to the button or in some text window.
Question - How can I pass the values received from this form back to foo?
Question - How can I return a text value back to the user?
The second - basic buttons which call a Python program and return and return some relative text back to the user (i.e., successful). I'm assuming I can use the above questions to answer this as well.
Documentation I continue to see online uses app.route and routes the user to another page with results. I want to keep the user on the same page and just return text. If this is too vague you can tell me to RTFM. Just having a hard time figuring this out.
See below for my code:
index.html:
<form action="/foo" method="post">
CHIPS:<br>
<input type="text" name="doritos"><br>
SNACKS:<br>
<input type="text" name="oreos"><br>
<input type="submit" value="Submit">
</form>
<form action="/coo" method="post">
<input type="submit" name="pita" value="pita"><br>
<input type="submit" name="chip" value="chip"<br>
</form>
app.py
from flask import render_template
from app import app
#app.route('/')
#app.route('/index')
def index():
return render_template("index.html", title='Home')
#app.route('/foo')
def foo():
try:
..receive user-input values..
..do some back end actions..
return 'Successful.'
except:
return 'Failed.'
#app.route('/coo')
def coo():
try:
if request.form['pita']:
..do some back end actions..
return 'Successful.'
elif request.form['chip']:
..do some back end actions..
return 'Successful.'
except:
return 'Failed.'
Flask has the Jinja2 built in (you're already using it in the form of render_template), so one simple solution to this problem could be to create a template with your forms, and pass a "success" or "fail" message to the template when data is posted.
Consider the following index.html template snippet:
<form action="/" method="post">
CHIPS:<br />
<input type="text" name="doritos"><br />
SNACKS:<br />
<input type="text" name="oreos"><br />
<input type="submit" value="submit">
</form>
{% if fooResponse is not none %}
{{ fooResponse }}
{% endif %}
<form action="/" method="post">
<input type="submit" name="pita" value="pita"><br />
<input type="submit" name="chip" value="chip"><br />
</form>
{% if cooResponse is not none %}
{{ cooResponse }}
{% endif %}
Your Python might then look something like this (assuming you don't want to navigate away from ///index, and based on your question I'm assuming that the output shown from each form is non-persistent and mutually exclusive):
#app.route('/')
#app.route('/index', methods=['GET', 'POST'])
def index():
if request.method == "GET":
return render_template("index.html")
if request.form["submit"] == "submit":
doritos = request.form["doritos"]
oreos = request.form["oreos"]
success = process(doritos, oreos)
return render_template("index.html", fooResponse="Successful" if success else "Failed")
elif request.form["submit"] == "pita":
success = process("pita")
return render_template("index.html", cooResponse="Successful" if success else "Failed")
elif request.form["submit"] == "chip":
success = process("chip")
return render_template("index.html", cooResponse="Successful" if success else "Failed")
You can link your form submission to an ajax call in javascript. The ajax function would send the data to an api, python would do all calculations and send a response. The ajax function receives that response in the front end and displays whatever text/data you want in the frontend.
Consider something like:
$.ajax({
type: "POST",
url: "/api/oreos-and-doritos",
dataType: "json",
contentType: "application/json",
data: JSON.stringify(data-from-form),
success: function (data) {
// do whatever changes are needed in the frontend,
// like displaying a message
$('#msg').text(data);
},
error: function (xhr, error, thrown) {
// do some error handling here
}
}));

Post values from an HTML form and access them in a Flask view

I have an HTML form that gets posted to a Flask route. However, request.form is empty. If I try to access one of the values by id, I get a 400 error. How do I post values from an HTML form and access them in Flask?
<form method="POST">
<input id="my_input" type="text" value="{{ email }}">
<input id="my_submit" type="submit" value="Submit">
</form>
#app.route('/page', methods=['POST', 'GET'])
def get_page():
if request.method == 'POST':
print(request.form) # prints ImmutableMultiDict([])
print(request.form['my_input']) # raises 400 error
return render_template('page.html')
Your input doesn't have a name attribute. That is what the client will pass along to the server. Flask will raise a 400 error if you access a form key that wasn't submitted.
<input name="my_input" id="my_input" type="text" value="{{ email }}">
You need to Specify the form Action method in the Html page, and then mention the HTML Text box name inside the Tag.
<form method="POST" action="/PythonFunctionName">
<input id="my_input" type="text" name="HTMLControlName" value="{{ email }}">
<input id="my_submit" type="submit" value="Submit">
</form>
And inside the .py module access the element using the name specified in the HTML tag.
#app.route('/PythonFunctionName', methods=['POST', 'GET'])
def getPage():
if request.method == 'POST':
strTextBoxVal= request.form['HTMLControlName'])
Print(strTextBoxVal)
return render_template('page.html')

Categories