Having trouble understanding CherryPy - python

I read through the tutorial on the cherrypy website, and I'm still having some trouble understanding how it can be implemented in a modular, scalable way.
Could someone show me an example of how to have cherrypy receive a simple http post to its root, process the variable in some way, and respond dynamically using that data in the response?

from cherrypy import expose
class Adder:
#expose
def index(self):
return '''<html>
<body>
<form action="add">
<input name="a" /> + <input name="b"> =
<input type="submit" />
</form>
</body>
</html>'''
#expose
def add(self, a, b):
return str(int(a) + int(b))
if __name__ == "__main__":
from cherrypy import quickstart
quickstart(Adder())
Run the script and then open a browser on http://localhost:8080

Are you asking for an example like this?
http://www.cherrypy.org/wiki/CherryPyTutorial#ReceivingdatafromHTMLforms
It receives input from forms.
You can return any text you want from a CherryPy method function, so dynamic text based on the input is really trivial.

Related

Python Flask / HTML - what is the proper way of displaying an output after HTML form submission?

I am very new to web-development (first project) and have started playing around in Flask. The other day I made a very simple temperature converter which I was running on my local host. The page had a form input to type a value, two radio buttons with Fahrenheit and Celsius to define the system of the value, then a convert button. Here is a screenshot:
Here is my Flask code ("main.py"):
from flask import Flask, render_template
from flask import request, redirect
import temperature, convert, determine_system
app = Flask(__name__)
#app.route('/')
def html():
return render_template('index.html')
#app.route('/convert', methods = ['POST'])
def convert():
temp = request.form['temperature']
system = request.form['system']
new_temp, destination_system = determine_system.determine_system(temp, system)
return render_template('convert.html', temp=temp, system=system, new_temp=new_temp, destination_system=destination_system)
if __name__ == "__main__":
app.run()
As you can see, the first function called "html()" initially renders the "index.html" file and the function "convert()" is executed upon clicking the "Convert" button. There are a few other functions that I have in other .py files in the directory that convert the number to the new system.
Here is the body of my "index.html" code:
<body>
<div id="banner">
<h1>Temperature Converter</h1>
<p class="lead">Use this tool to convert temperature between measurement systems</p>
</div>
<form action="/convert" method="post" target="dummyframe">
<input type="text" name="temperature"></input>
<input type="radio" name="system" value="Fahrenheit">Fahrenheit</input>
<input type="radio" name="system" value="Celsius">Celsius</input>
<br>
<br>
<input type="submit" value="Convert"></input>
</form>
</body>
</html>
To display the converted temperature on the webpage, I currently have another HTML file called "convert.html" in my templates directory that is an exact copy of the "index.html" file, except it includes the following three lines of code in the body after the :
div id="output"></div>
<p class="output-statement">{{ temp }}° {{ system }} is equal to {{ new_temp }}° {{ destination_system }}</p>
</div>
In my Flask file ("main.py), I instruct the "convert()" function to render the "convert.html" template which includes the output statement in the code above:
return render_template('convert.html', temp=temp, system=system, new_temp=new_temp, destination_system=destination_system)
This then results in the following (notice the new web address):
I suspect that my way of outputting the converted temperature by redirecting to a new HTML file and web address (http://127.0.0.1:5000/convert) is not efficient or even the correct way of showing accomplishing this. What is the proper way to output something like this? Is there something I can add to the "index.html" file that would allow me to get rid of the "convert.html" file completely? If so, what would I change the last line of the "convert()" function in my Flask ("main.py") file to?
Thank you in advance and any links with more information on this concept are very appreciated!
Yes there is a more efficient solution where you do not need the convert.html:
This is what you will want in your main route. (note: I suggest renaming your route function to something like "index" or "temp" other than "html")
#app.route('/', methods=["GET","POST"])
def html():
output = ""
if request.method == "POST":
temp = request.form['temperature']
system = request.form['system']
new_temp, destination_system = determine_system.determine_system(temp, system)
output = f"{ temp}° { system } is equal to { new_temp }° { destination_system }"
return render_template('index.html', output=output)
Make sure to import request. using: from flask import request
and in your index.html you will now have:
<div id="output"></div>
<p class="output-statement">{{output}}</p>
</div>
And make sure to change form action to action="#" or action=""

Connecting python script with html button and flask

I am trying to create a webapp and am fairly new to it. I have a python script(file.py) that transforms data selected by a user. It handles all the inputs and outputs.
I am using flask(main.py) for the server part of it and html. I want to place a button in my html code so it will start the execution of the file.py. Can anyone assist me with an example setup for the connections between the 3?
I've looked at other examples but I'm unable to recreate it as they're doing different things. Also, file.py is fairly large so I want to avoid putting it into a function.
Edit: not looking for a flask tutorial. I've tried 3things:
A shell pops up for half a second but the disappears. Then I'm redirected to a page which just has the text in my return statement
in my html file
<form action="/pic" method="POST">
<input type="submit" value="GET THE SCRIPT">
</form>
in my main.py flask file
#app.route('/pic', methods=['GET', 'POST'])
def pic():
os.system("python file.py") #file.py is the script I'm trying to start
return "done"
Doesn't do anything at all.
in html file:
<input type="button" id='script' name="scriptbutton" value=" Run Script " onclick="goPython()">
<script src="http://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script>
function goPython(){
$.ajax({
url: "/scripts/file.py",
context: document.body
}).done(function() {
alert('finished python script');;
});
}
</script>
I get a GET "/scripts/file.py HTTP/1.1" 404 message. I have my scripts folder in the same directory as my templates folder. Also tried placing the scripts folder inside the templates folder.
in html
<form action="/run" method = "POST">
<input type="button" id='script' name="submit" value="Run Scripttttttt">
</form>
in flask main.py
#app.route('/run',methods=['GET', 'POST'])
def index():
def inner():
proc = subprocess.Popen(
['python file.py'],
shell=True,
stdout=subprocess.PIPE
)
for line in iter(proc.stdout.readline,''):
time.sleep(1)
yield line.rstrip() + '<br/>\n'
return Flask.Response(inner(), mimetype='text/html')
Using an HTML Anchor tag (i.e ) is the easiest way. Here is an example:
This is a link
But since you've chosen button, JavaScript will come in handy. Here's an example(inline):
<button onclick="window.location.href='your_flask_route';">
This is a link
</button>
and then in your flask main.py file you should have this:
#app.route('/your_flask_route')
def your_flask_route():
'''some lines of code'''
You can set up a Flask endpoint that your button can send a request to. Then let the endpoint's function call your python script.
Have a look at this discussion about Flask - Calling python function on button OnClick event and this discussion about How can I make one python file run another? to get you started.

How do I receive an excel file as input using Flask and read it using openpyxl?

I've created a python script that loads an excel file up from my computer and, after working with the information inside it using openpyxl, saves a new excel file. The script works on my computer. For longevity purposes, I want to make the script into a website, using pythonanywhere or something similar to it (incorporating flask seemed like the best way to convert my script into a website). However, I am having trouble finding a way to accept a file from the user, as I have very little experience using flask. Here's the code I currently have that creates a "choose file" button and a "process file" button:
app = Flask(__name__)
app.config["DEBUG"] = True
#app.route("/", methods=["GET", "POST"])
def file_summer_page():
if request.method == ("POST"):
input_file = request.files["input_file"]
wb_master = load_workbook(input_file)
output_data = main(wb_master)
response = make_response(output_data)
response.headers["Content-Disposition"] = "attachment; filename=result.csv"
return response
return '''
<html>
<body>
<p>Load up the automated eval that MS Forms gives you:</p>
<form method="post" action="." enctype="multipart/form-data">
<p><input type="file" name="input_file" /></p>
<p><input type="submit" value="Process the file" /></p>
</form>
</body>
</html>
'''
Bear with me. Again, I haven't used Flask much, but this is my idea so far. Main(wb_master) essentially calls the script I made, so that it could hopefully run. At the moment, this returns the following error: "AttributeError: 'SpooledTemporaryFile' object has no attribute 'seekable'." In this case, I don't really know what it means, but I assume it is due to the fact that I am not reading the file correctly. Any help would be greatly appreciated!

Basic Form In Flask Causing HTTP 400 - Python 3.5

I am new and have spent hours trying to setup a form in Flask for Python 3.5. I want the user to be able to enter a temperature setpoint and click submit button, and have the value stored in a variable.
I have this code in a template file called index.html:
<html>
<body>
<p><font size="6">Jewell Hot-Tub Controller</font>
<br>
<font size="4">Water Temperature: {{water_temp}}</p>
<br>
<font size="4">Set Point: {{set_point}}</p>
<br>
<font size="4">Enter New Set Point:</p>
<form class="form-newtemp" method="get" action="/ChangeTemp">
<input type="text" id="new_sp" name="new_sp" size="5" placeholder="New Temp." required>
<input id="1submit" type="submit">
</form>
</body>
</html>
and this code in the "flask-test.py" file:
from flask import Flask, render_template, request
app = Flask(__name__)
app.debug = True
#app.route('/')
def index():
return render_template('index.html', water_temp='12345')
#app.route('/ChangeTemp', methods=['GET'])
def process():
new = request.form['new_sp']
return 'New set point is:' + new
Entering "27" in the textbox sends the browser to a 400 Bad Request page at:
http://127.0.0.1:5000/ChangeTemp?new_sp=27
Why does this change a bad request error, rather than returning the value? The tutorials I saw used POST, but I used GET, does this require different syntax?
Also, please let me know if anything is messy, or done wrong.
Thank you!
EDIT: I also tried "request.form.get('new-sp', new)" and this causes a 500 internal server error.
multiple ways to fix your problem. i guess the fastest way is:
<form class="form-newtemp" method="post" action="{{ url_for('process')}}">
and then
#app.route('/ChangeTemp', methods=['POST])
def process():
new = request.form['new_sp']
return 'New set point is:' + new
or you can go with not changing your template and:
#app.route('/ChangeTemp', methods=['GET'])
def process():
new = request.args.get('new_sp')
return 'New set point is:' + new

how to send response to html using cgi python script

I am trying to design and implement a basic calculator in HTML and Python(using CGI). Below given is a static HTML web page and it is being redirected to a python script (calci.py) where, I am able to calculate the sum but unable to append the resultant to the 'output' textbox.
calculator.html
<html>
<head>
<title>Calculator</title>
</head>
<body>
<form action="python_scripts/calci.py" method="post">
Input 1 : <input type="text" name="input1"/><br>
Input 2 : <input type="text" name="input2"/><br>
<input type="submit" value="+" title="add" /><br>
output : <input type="text" name="output"/><br>
</form>
</body>
</html>
calci.py
import cgi
form = cgi.FieldStorage()
input1 = form.getvalue('input1')
input2 = form.getvalue('input2')
output = str(int(input1)+int(input2))
#how to return the response to the html
#and append it to the textbox
Thanks
This is not the way Web applications work - not hat simply, at least.
If you want to rely only on the browser, and plain HTML for your application, each request has to send the whole html page as a string. You have to use Python's string formatting capabilities to put the resulting number in the correct place in the HTML form.
This way of working is typical of "Web 1.0" applications (as opposed to the "Web 2.0" term used about ten years ago).
Modern web applications use logic that runs on the client side, in Javascript code, to make an HTTP request to retrieve only the needed data - and them, this client-side logic would place your result in the proper place in the page, without reloading the page. This is what isgenerally known as "ajax". It is not that complex, but the html + javascript side of the application become much more complex.
I think one should really understand the "Web 1.0" way before doing it the "Ajax way". in your case, let's suppose your HTML containing the calculator form is in a file called "calc.html". Inside it, where the result should lie, put a markup that can be understood by Python's built-in native string formatting methods, like {result} -
<html>
<body>
...
calculator body
...
Answer: <input type="text" readonly="true" value={result} />
</body>
</html>
And rewrite your code like:
import cgi
form = cgi.FieldStorage()
input1 = form.getvalue('input1')
input2 = form.getvalue('input2')
result = int(input1)+int(input2)
html = open("calc.html".read())
header = "Content-Type: text/html; charset=UTF-8\n\n"
output = header + html.format(result=result)
print (output)
The CGI way is outdated, but is nice for learning: it relies on your whole program being run, and whatever it prints to the standard output to be redirected to the HTTP request as a response. That includes the HTTP Headers, which are included, in a minimal form, above.
(I will leave the complete implementation of a way for the raw '{result}' string not to show up in the inital calculator form as an exercise from where you are 0- the path is to get the initial calculator html template through a CGI script as well, instead of statically, (maybe the same) as well - and just populate "result" with "0" or an empty string)
you can transfer response with the help of java script.
use under print("window.location=url")

Categories