I am trying to use flask to get data from a html form. The form shows up on the website ok, but when I submit python doesn't receive it.
Html code:
<form action="/signup" method="post">
<input type="text" name="email"></input>
<input type="submit" value="signup"></input>
</form>
Python code:
from flask import Flask, render_template, request, redirect
app = Flask(__name__)
#app.route('/')
def home():
return render_template('home.html')
#app.route('/about/')
def about():
return render_template('about.html')
#app.route('/signup', methods = ['POST'])
def signup():
email = request.form['email']
print("The email address is '" + email + "'")
return redirect('/')
if __name__ == '__main__':
app.run(debug=True)
APP
--static
----main.css
--templates
----html code(home.html)
python code(hello.py)
The code works fine for me.
The only thing I would change is using the url_for() construct instead of directly specifying your endpoints.
I.E.: use return redirect(url_for('home'))
Alternatively, try to provide a GET request for your 'signup' endpoint.
Add 'GET' to your methods argument
Put your printing block under an if statement (if request.method == "POST")
Underneath this block put something to return. (return redirect(url_for('home')), return render_template('xyz.html'), etc.)
Related
Say I have an example flask app which basically is a small webform that would take in user input data called applet.py.(The code is taken from a online blog that shows an example flask app build).
from flask import Flask,render_template,request
app = Flask(__name__)
#app.route('/form')
def form():
return render_template('form.html')
#app.route('/data/', methods = ['POST', 'GET'])
def data():
if request.method == 'GET':
return f"The URL /data is accessed directly. Try going to '/form' to submit form"
if request.method == 'POST':
form_data = request.form
return render_template('data.html',form_data = form_data)
app.run(host='localhost', port=5000)
The input is captured in this below form.
<form action="/data" method = "POST">
<p>Name <input type = "text" name = "Name" /></p>
<p>City <input type = "text" name = "City" /></p>
<p>Country <input type = "text" name = "Country" /></p>
<p><input type = "submit" value = "Submit" /></p>
</form>
If I were wanting to send this received user input into ansible variables and then trigger the ansible script to run and execute the playbook based on the given variables. How can I do that? I have googled a lot around this, couldn't find a suitable example that fits my use case. (Disclaimer, not very knowledgeable about both flask and ansible, learning as I do). Appreciate help, reference and advice.
You can use the ansible_runner module to run your playbook (docs).
import ansible_runner
#app.route('/data/', methods = ['POST', 'GET'])
def data():
if request.method == 'GET':
return f"The URL /data is accessed directly. Try going to '/form' to submit form"
if request.method == 'POST':
form_data = request.form.to_dict()
r = ansible_runner.run(playbook='test.yml', extravars=form_data)
# check ansible return code
if r.rc != 0:
abort(400, 'Ansible error')
return ('', 204)
If your playbook takes some time to run you might be better adding the job of running it to a queue and processing it separately.
I’m new to web development. I have learned how to make a web sever using flask. What I want to do is make an html button run python code from the web server when it is clicked. Is this even possible? If so, can someone point me to some html examples that can do that?
Update: I think I found some code that might work with what I’m asking. I don’t know for sure if it would work or not.
Here is the link:
Call a python function within a html file
If I were to convert the “click a link” aspect of the code to “click a button” would it run my python code on the viewers end, not my end?
It is Possible in Two ways
Create an HTML form and button to submit the form. The from can call the post URL on the flask server
Add some javascript to the HTML and call any HTTP method /url that you have created using the flask server.
You can use button with form or with JavaScript
Form
Normally to use button you need <form> which sends request to Flask to url defined in action="..." and Flask sends back response (text/HTML) and browser automatically put it in window in place of previous HTML - so server has to generate full HTML again and again.
from flask import Flask, request, render_template_string
import datetime
app = Flask(__name__)
#app.route('/')
def index():
return render_template_string('''<form action="/page" method="POST">
<button type="submit" name="btn" value="Button 1">Button 1</button>
<button type="submit" name="btn" value="Button 2">Button 2</button>
<button type="submit" name="btn" value="Button 3">Button 3</button>
</form>''')
#app.route('/page', methods=['GET', 'POST'])
def page():
value = request.form.get('btn') # gives text from `value="Button 1"`
return f'You pressed {value} at ' + datetime.datetime.now().strftime('%Y.%m.%d %H:%M.%S')
if __name__ == '__main__':
#app.debug = True
app.run() #debug=True
And the same using empty action="" so it sends request to the same url and it needs to check request.method to run different code
from flask import Flask, request, render_template_string
import datetime
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
value = request.form.get('btn') # gives text from `value="Button 1"`
info = f'You pressed {value} at ' + datetime.datetime.now().strftime('%Y.%m.%d %H:%M.%S')
else:
info = ""
return render_template_string('''<form action="" method="POST">
<button type="submit" name="btn" value="Button 1">Button 1</button>
<button type="submit" name="btn" value="Button 2">Button 2</button>
<button type="submit" name="btn" value="Button 3">Button 3</button>
</form>{{text}}''', text=info)
if __name__ == '__main__':
#app.debug = True
app.run() #debug=True
JavaScript
If you want to execute Flask code without reloading all HTML then you need to use JavaScript which can send request to server using old
XMLHttpRequest or modern fetch(), get response and replace only part of HTML. Often in this method server sends JSON data and JavaScript may use it to replace HTML in different places.
And this method need to learn JavaScript to create something more complex.
from flask import Flask, request, render_template_string
import datetime
app = Flask(__name__)
#app.route('/')
def index():
return render_template_string('''
<button onclick="my_function()">Get Time</button>
<span id="time">Press Button to see current time on server.</span>
<script>
span_time = document.querySelector("#time");
function my_function(){
fetch('/get_time')
.then(res => res.text())
.then(text => span_time.innerHTML = text);
}
</script>
''')
#app.route('/get_time')
def time():
return datetime.datetime.now().strftime('%Y.%m.%d %H:%M.%S')
if __name__ == '__main__':
#app.debug = True
app.run() #debug=True
In examples I use render_template_string instead of render_template to make code simpler - now everyone can copy code and paste to one file and run it.
I am able to pass data from one html form to a second html page using Flask. But when I try to pass the data from the second html page to a third html page, i get an error:
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'binary'
I am basically trying to input binary numbers on the first html page, convert it to a decimal on the second html page, and then convert it to a hexadecimal number on the third page. Here is my Flask code:
from flask import Flask, redirect, url_for, render_template, request
app = Flask(__name__)
#app.route('/', methods=['POST','GET'])
def input_binary():
if request.method == "POST":
binary = request.form["binary"]
return redirect(url_for("show_decimal", bin=binary))
else:
return render_template("binary.html")
#app.route('/<bin>', methods=['POST','GET'])
def show_decimal(bin):
if request.method == "POST":
decimal = request.form["decimal"]
return redirect(url_for("show_hex", dec = decimal))
else:
decimal = int(bin,2)
return render_template("decimal.html", dec=decimal)
#app.route('/<dec>', methods=['POST','GET'])
def show_hex(dec):
hexadecimal_string = hex(int(dec))
return render_template("hex.html", hex = hexadecimal_string)
if __name__ == "__main__":
app.run(debug=True)
It seems like when i click submit on the second page again, it's trying to run the code from the def input_binary function and not the def show_hex function. Maybe it has to do with the submit button on the second page?
This is the html on the second html page:
<body>
<p>{{dec}}</p>
<form name="decimalNumber" action="." method="POST">
<label>Input the decimal number</label>
<input type="number" name="decimal">
<input type="submit" value="submit">
</form>
</body>
Any suggestions?
first, your input name "binary" may be conflicted with http protected keyname. try another name. you can see What is the cause of the Bad Request Error when submitting form in Flask application?
I am trying to make a web-app using flask, and I am having a problem redirecting to another page/route that I have in my app.py file. I also set up a HTML template for the other (login) page.
Here is my code in the main app.py:
#app.route('/', methods=['GET', 'POST'])
if request.method == 'GET':
pass
if request.method == 'POST':
pass
return render_template('index.html', passable=passable)
#app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
name = request.form.get('username')
post = request.form.get('password')
# still need to complete
return render_template('login.html')
I have imported all the relevant modules (I think).
In my Index.html file, I have a button, which I would like it to redirect to my login.html page. Currently I am doing something like this:
<button type="submit" onclick='{{Flask.redirect(url_for(login))}}' value="editor">
Whenever I launch the page (locally) i get this error.
jinja2.exceptions.UndefinedError
jinja2.exceptions.UndefinedError: 'Flask' is undefined
How do I make my button redirect to the "login" flask route?
If you want your form to submit to a different route you can simply do <form action="{{ url_for('app.login') }}">.
If you just want to put a link to the page use the <a> tag.
If you want to process the request and then redirect, just use the redirect function provided by flask.
<a href="{{url_for(app.login)}}" >Login</a>
I have an HTML index page that sends input data to a python script which processes the data and outputs it in a 2nd HTML page. On a local host, the process works fine and the data is displayed as desired. But when I try to host the process online, I get an error saying the URL cannot be found. If it helps, I'm using Heroku.
Apologies in advance for any poor lingo. I only just started learning how to code recently.
1st HTML
<form action = "https://webaddress/result" method = "POST">
<h1> Enter info: </h1>
<input type="text" name="info">
<input type="submit" value="Submit"/>
</form>
Python:
from flask import Flask, render_template, request
from bs4 import BeautifulSoup
import requests
# https://doi.org/10.2118/21513-MS
app = Flask(__name__)
#app.route('/')
def student():
return render_template('Trial.html')
#app.route('/result.html',methods = ['POST', 'GET'])
def result():
return render_template("result.html",result = output)
if __name__ == '__main__':
app.run(debug = True)
The input in the 1st HTML would be sent to the python section to be broken down and rearranged (left out that part so the python code wouldn't be too long) before being output into result.html. This worked on a local host using http://localhost:5000/ and http://localhost:5000/result.
When I run it on Heroku, I get the error message:
Not Found
The requested URL /result was not found on this server.
Update: Problem solved.
Having some issues understanding your results() function. output isn't defined anywhere and type isn't used at all.
I believe your action parameter is incorrect.
Try:<form action="/result" method = "POST">
Here is a working version of what I hacked together for you:
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/', methods=['GET'])
def home():
return '''
<form action="/result" method = "POST">
<h1> Enter info: </h1>
<input type="text" name="info">
<input type="submit" value="Submit"/>
</form>
'''
#app.route('/result',methods = ['POST', 'GET'])
def result():
if request.method == 'POST':
type = ''
if 'info' in request.form:
result = request.form['info']
return result
if __name__ == '__main__':
app.run(debug=True, port=8888, host='0.0.0.0')
Your form refers to /result (no .html extension), but your route is for /result.html (with the extension). Try removing the .html from your route:
#app.route('/result', methods=['POST', 'GET'])
def result():
return render_template("result.html", result=output)