I have read many other answers here, but find that following them doesn't still work for me.
What I want is for one python script which runs Flask to get a value submitted from an html form, and then pass it into an argument for a second python script that is triggered from the first python script.
My python Flask code is as below:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Webapp.py
from flask import Flask, render_template, request
import datetime
import os
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/')
def my_form():
return render_template("my-form.html")
#app.route('/', methods=['POST'])
def my_form_post():
text = request.form['field1']
mid = text.upper()
now = datetime.datetime.now()
timeString = now.strftime("%d-%m-%Y %H:%M:%S")
IDData = {
'title' : mid,
'time': timeString
}
print('ID is: {0}'.format(mid))
os.system("sudo python /home/pi/Add/triggertest.py mid")
return render_template('cp.html', **IDData)
if __name__ == "__main__":
try:
app.run(host='0.0.0.0', port=80, debug=True)
except KeyboardInterrupt:
logfile.close()
My html for index file is as below:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>HEAT</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href='/static/style.css' />
</head>
<body>
<img src="/logo.png" alt="LOGO" style="width:168px;height:56px;">
<h1>"HEAT"</h1>
<div id="time">
<h3>The current date and time on the server is: {{ time }}</h3>
</div>
<!--
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
function autoRefresh_div()
{
$("#time").load("cp.html");// a function which will load data from other file after x seconds
}
setInterval('autoRefresh_div()', 0500); // refresh div after 0.5 secs
</script>
-->
<form action="" method="POST">
<ul class="form-style-1">
<li><label>Melt ID <span class="required">*</span></label></li>
<li>
<input type="text" name="field1" class="field-divided" placeholder="Please enter the meltID here"/>
</li>
<li>
<input type="submit" name="my-form" value="Submit" />
</li>
</ul>
</form>
</body>
</html>
My cp.html is as below:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Control Panel</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href='/static/style.css' />
</head>
<body>
<div id="time">
<!--
<code>
#app.route('/my-form', methods=['POST'])
def my_form_post():
text = request.form['field1']
processed_text = text.upper()
now = datetime.datetime.now()
timeString = now.strftime("%d-%m-%Y %H:%M:%S")
IDData = {
'title' : processed_text,
'time': timeString
}
return render_template('cp.html', **IDData)</code>-->
<h3>The melt ID is: {{ IDData }}</h3>
</div>
</body>
</html>
My code for second python script triggertest.py is:
# -*- coding: utf-8 -*-
#!/usr/bin/python
# For logging debug output:
#import logging
#logging.basicConfig(level=logging.DEBUG)
import time
import os
import sys
import Adafruit_GPIO.SPI as SPI
import Adafruit_MAX31855.MAX31855 as MAX31855
from datetime import datetime
# Define a function to convert celsius to fahrenheit.
def c_to_f(c):
return c * 9.0 / 5.0 + 32.0
# Raspberry Pi software SPI configuration.
#CLK = 25
#CS = 24
#DO = 18
#sensor = MAX31855.MAX31855(CLK, CS, DO)
# Raspberry Pi hardware SPI configuration.
SPI_PORT = 0
SPI_DEVICE = 0
sensor = MAX31855.MAX31855(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))
def write_temp(t, logfile):
#Writes temperature as .3 float to open file handle.
logfile.write('{},{:.3f}\n'.format(datetime.now().strftime('%d-%m-%Y %H:%M:%S'), t))
def loop(t, logfile):
#Starts temperature logging until user interrupts.
while True:
#temp = sensor.readTempC()
t = sensor.readTempC()
if t:
write_temp(t, logfile)
#print('Current temperature: {0:.3f} °C'.format(t))
sys.stdout.flush() #Flush. Btw, print is time-consuming
time.sleep(.25)
# Instructions for exiting the program
print('Trigger testing in progress. Press Ctrl-C to quit.')
if __name__ == '__main__':
# The next two lines are for using DS18B20 temperature sensor
# Take the first match for a device that is not 'w1_bus_master1'
#dev = [d for d in os.listdir('/sys/bus/w1/devices') if d != 'w1_bus_master1'][0]
# Prepare the log filename
fname = str(sys.argv[1]) + "-" + datetime.now().strftime("%d-%m-%Y-%H-%M-%S")+".csv"
# Immediately open the log in append mode and do not close it
logfile = open(fname, 'a')
try:
# Only pass device and file handle, not the file name.
t = sensor.readTempC()
internal = sensor.readInternalC()
loop(t, logfile)
print('Thermocouple Temperature: {0:0.3F}*C / {1:0.3F}*F'.format(t, c_to_f(temp)))
print(' Internal Temperature: {0:0.3F}*C / {1:0.3F}*F'.format(internal, c_to_f(internal)))
#time.sleep(1.0)
except KeyboardInterrupt:
# Close log file on exit
logfile.close()
My problems are:
Script #2 (triggertest.py which logs temperature) is starting, but it is not logging anything. I guess because the argument is not being passed?
I can end script #2 with Ctrl-C, but script #1 with flask remains running, which makes me need to restart the raspberry pi to run/test everything again.
Any ideas?
P.S. I have put 4 codes here making this file too long, and I apologize for that. I am a newbie to HTML and Python, and hence stuck here.
Related
I am trying to display a timer of 5minutes (for example). I am using flask.
I know it could be good to use javascript but I really want to do it with python.
I have two issues:
First issue: display of the timer - issue to overwrite
I wrote a function for the timer in python which is supposed to display (for example for 50 seconds):
00:50 then remove 00:50 and have00:49, and so on...
But it is displaying:
00:50
00:49
00:48
...
Here is my code: screen.py
from flask import Flask, Response, request, render_template, render_template_string, stream_with_context
import time
app = Flask(__name__)
timing=0
#app.route('/content', methods=['POST', 'GET']) # render the content a url differnt from index. This will be streamed into the iframe
def content():
global timing
timing = 10
# if request.form.get("submit"):
# timing = request.form['timing']
# print(timing)
def countdown(t):
while t:
mins, secs = divmod(t, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
print(timer, end="\r")
yield timer
time.sleep(1)
t -= 1
# return timer
return app.response_class(countdown(timing)) #at the moment the time value is hardcoded in the function just for simplicity
# return render_template('display.html')
#app.route('/')
def index():
value = "Bonjour"
title_html = value
return render_template('display.html', message=title_html) # render a template at the index. The content will be embedded in this template
if __name__ == '__main__':
app.run(use_reloader=False)
I would like to find the equivalence of print(timer, end="\r") for yield in order to overwrite the value of timer and not see all the results when it's decreasing. I hope my explanation is clear.
Second issue: Input value of the timer
As you can see in my code screen.py, my value for timing is hardcoded timing=10. But I would like to allow the user to enter the value he wants in input like that:
if request.form.get("submit"):
timing = request.form['timing']
print(timing)
You can see these lines in screen.py, I commented them to leave timing=10 because when I write these lines I obtain the following error:
Method Not Allowed
The method is not allowed for the requested URL.
127.0.0.1 - - [02/Aug/2021 12:50:26] "POST / HTTP/1.1" 405 -
Here is the HTML Code linked to my python code display.html:
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" href='/static/main.css'/>
<title>your dish</title>
</head>
<body>
<h1>{{message}}! Here are some informations about your dish:</h1>
<h2> countdown </h2>
<!-- <p>{{message}}</p> -->
<form method="POST" action=".">
<p><input name="timing" value="{{timing}}" placeholder="Enter your time"></p>
<input type="submit" name="submit" value="submit">
</form>
<div>
<iframe frameborder="0" noresize="noresize"
style='background: transparent; width: 100%; height:100%;' src="{{ url_for('content')}}"></iframe>
</div>
</body>
</html>
How can I avoid this error and take into consideration the value entered by the user in the input field of my display.html?
I tryed to run your script locally but I am not sure where do you expect to see the timer; I assume you used the countdown func from here.
I would like to propose you a different approach: stream dynamically the counter to the web page using an iframe:
from flask import Flask, render_template, Response
import time
app = Flask(__name__)
#app.route('/content') # render the content a url differnt from index. This will be streamed into the iframe
def content():
def timer(t):
for i in range(t):
time.sleep(5) #put 60 here if you want to have seconds
yield str(i)
return Response(timer(10), mimetype='text/html') #at the moment the time value is hardcoded in the function just for simplicity
#app.route('/')
def index():
return render_template('test.html.jinja') # render a template at the index. The content will be embedded in this template
if __name__ == '__main__':
app.run(use_reloader=False)
then add an iframe where do you prefer in your html
<!doctype html>
<head>
<title>Title</title>
</head>
<body>
<h2> countdown </h2>
<div>
<iframe frameborder="0" noresize="noresize"
style='background: transparent; width: 100%; height:100%;' src="{{ url_for('content')}}"></iframe>
</div>
</body>
The result will be a dynamic countdown on your web-page
countdown
0123456789
you can see it done quick and dirty here on my repl
While it's not tuned around your application yet, (and not particularly beautiful graphically) you can modify the function to accept an input from the user with a form (I see you actually did already in your app), or also tune the countdown function directly.
t = request.form['t']
and adding to your html the form
<form method="post" action=".">
<p><input name="t" placeholder="your time"/></p>
<p><input type="submit" value="Submit"/></p>
</form>
You have the same route #app.route("/") appearing 3 times. The system will pick the first one which simply displays display.html. And I suspect even that will currently not work because your page is expecting values for message, timing but those attributes don't exist in your first route.
You should try something like
#app.route("/", methods=['POST', 'GET'])
def display():
page = 'display.html'
params = {"message":"", "timing":0} # initialize values for both message and timing. These will be returned when user loads the page (a GET call)
if request.method == 'POST':
timing = request.values.get("timing")
# do whatever processing you want
params["timing"] = <your computed value>
params["message"] = <your message>
params["message_2"] = <your other message>
return render_template(page, **params)
Delete all the other routes you have for #app.route("/")
I am new to Python and trying server side form handling. I have a simple html page with three input fields and and a textarea. When user fill in the details the form is processed and user presented with all the details he filled in. My only issue is that I can't get new line to work while printing the data in the main program after htmlTop() function. Tried many ways but without luck.
Following is my code that I have tried so far.
#!C:\Python34\python.exe
import cgi
def htmlTop():
print("""Content-type:text/html\n\n
<!Doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title> Server Template </title>
</head>
<body>""")
def htmlTail():
print("""</body>
</html>""")
def getData():
formData = cgi.FieldStorage()
firstname = formData.getvalue('firstName')
lastname = formData.getvalue("lastName")
email = formData.getvalue('email');
message = formData.getvalue('message')
dataList = [firstname , lastname , email , message]
return dataList
#main program construct
if __name__ == "__main__":
try:
htmlTop()
data = getData();
print("Welcome! {1} {0}".format(data[0],data[1]))
print("\n" + "Your email is {0}".format(data[2]))
print("\n" + "Your entered the following message: {0}".format(data[3]))
htmlTail()
except:
cgi.print_exception()
Try using <br> to add a line break instead of a newline character.
I have created a dashboard using python. I have a requirement to make some cosmetic changes in the html page.
Change the font and size
Changing the background color
Putting one company logo.
I researched with turtle and tkinter,and installed the same but the system is not recogonizing the modules. Is there a way to achieve the above functionality.
Source code is as below
#!/usr/local/bin/python
import requests
import json
import datetime
import sys
import os
from html import HTML
todayDate=datetime.date.today().strftime("%Y-%m-%d")
h=HTML('html','')
p=h.p('DETAILS for ',' ', todayDate)
t=h.table(border='1')
r=t.tr()
r.td('Import Timestamp')
r.td('JobId')
r.td('Status')
r.td('RecordsProcessed')
r.td('RecordsFailed')
r.td('FileName')
r.td('Duration')
r.td('Throughput')
print '\n'
def genHTMLforImportSuccess():
responseurl = requests.get(url)
if(responseurl.ok):
jData = json.loads(responseurl.content)
if jData > 0:
for responseurl in jData['response']:
starttime=responseurl['statistics']['startTime']
jobId= responseurl['jobId']
status = responseurl['status']
recordsProcessed=responseurl['statistics']['recordsProcessed']
recordsFailed=responseurl['statistics']['recordsFailed']
fileName=responseurl['fileName']
duration=responseurl['statistics']['duration']
throughput=responseurl['statistics']['throughput']
print '\n'
r=t.tr()
r.td(str(starttime))
r.td(str(jobId))
r.td(str(status))
r.td(str(recordsProcessed))
r.td(str(recordsFailed))
r.td(str(fileName))
r.td(str(duration))
r.td(str(throughput))
print '\n'
else:
print "No data feed"
else:
responseurl.raise_for_status()
genHTMLforImportSuccess()
print h
Any help is highly appreciated
I added the below code after the
from html import HTML
html = """
<!doctype html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>testpage </title>
<style>
body {
background-color: aqua;
}
</style>
</head>
<body>
</body>
</html>
"""
but could not get the desired result.how can i fix this
I am trying to put a simple python script (here I've used a random two-word generator which works fine) in a div on a webpage with Ajax and have a button beneath that reloads it. The page successfully loads the script... however, I haven't quite got my head around the missing part to call the script again to reload the random two words made by the python script (I understand why the code below is wrong but I can't work out how to make it right!). Pointer much appreciated!
(N.B. Yes I am using Python 2.4 because my web host hasn't upgraded yet - they will soon! And yes I saw this question but it didn't work for me...)
HTML:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
<title>Find a sentence</title>
<script src="http://code.jquery.com/jquery-2.0.3.js"></script>
<script>
$(function()
{
$.ajax({
url: "cgi-bin/test.py",
type: "GET",
data: {foo: 'bar', bar: 'foo'},
success: function(response){
$("#div").html(response);
}
});
});
</script>
</head>
<body>
<div id="div"></div>
<form name="input" action="cgi-bin/test.py" method="get">
<input type="submit" value="Regenerate!">
</form>
</body>
PYTHON:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# enable debugging
import cgitb
cgitb.enable()
import linecache
from random import randrange
print "Content-Type: text/html"
print
# file length counter
def file_len(fname):
f = open(fname)
try:
for i, l in enumerate(f):
pass
finally:
f.close()
return i + 1
# range sizes
one_size = file_len('text/one.csv')
two_size = file_len('text/two.csv')
# random lines
one_line = randrange(one_size) + 1
two_line = randrange(two_size) + 1
# outputs
one_out = linecache.getline('text/one.csv', one_line)
two_out = linecache.getline('text/two.csv', two_line)
# output
sentence = one_out.strip('\n') + " " + two_out.strip('\n') + " "
print sentence
Well, I would assume that one has to click on the "Regenerate" button for the form to reload. My idea would be to have the ajax logic in a separate function. I don't think you need the form there since your reload call is now ajax call.
<head>
<script>
function reload() {
$.ajax({
url: "cgi-bin/test.py",
type: "GET",
data: {foo: 'bar', bar: 'foo'},
dataType : "html",
success: function(response){
$("#div").html(response);
}
});
}
$(window).load(function() {
reload();
$("#reload_button").click(function() {
reload();
});
});
</script>
</head>
<body>
<div id="div"></div>
<input type="button" id="reload_button" value="Regenerate!">
</body>
I created a server with python.
Now I have a webpagecgi to screen my result and also a svg file.
I tested 3 ways to that:
Solution1 a javascript method to load quicky the svg (works out of server-> but not in the localserver)
Solution2 a simple object import (works out of server -> but not in the localserver)
Solution3 svg inside the html (works out and in the server)
I would like to use the solution 1 or 2 because the 3 is not comfortable and dirty for me...
Why Solution1 and 2 does not work? I think they do not find svg file but I don't understand why...
os.system("cp %s WEBSERVER/toto.svg"%(svg))
print 'Content-type: text/html' #application/xhtml+xml'# image/svg+xml'
print '''
<html>
<head>
<script language="javascript">
function loadSVG(id, svg) {
var element = document.getElementById(id);
var object = document.createElement("object");
object.type = "image/svg+xml";
object.data = svg;
element.appendChild(object);
}
</script>
</head>
<body>
SOLUTION1<br/>
<script type="text/javascript">
loadSVG('hca', 'WEBSERVER/toto.svg');
</script>
SOLUTION2<br/>
<object type='image/svg+xml' data ='WEBSERVER/toto.svg'></object>
SOLUTIONT3<br/>
<svg xmlns="http://www.w3.org/2000/svg"
width="800" height="800" >
<rect x="50" y="200" width="250" height="40" />
</svg>
</body>
</html>
'''
Here is the webserver that I launch in python:
#!/usr/bin/python
import BaseHTTPServer
import CGIHTTPServer
import cgitb; cgitb.enable()
server = BaseHTTPServer.HTTPServer
handler = CGIHTTPServer.CGIHTTPRequestHandler
server_address = ("0.0.0.0", 8123)
handler.cgi_directories = ['/WEBSERVER']
httpd = server(server_address, handler)
try:
print "Running HTTP server"
httpd.serve_forever()
except KeyboardInterrupt:
print "Server Stoped"