I hope you can help me.
The fact is that I want to implement the transfer of values from the sliders to the image processing function.
Interface picture
html code:
<form name="uploader" enctype="multipart/form-data" method="POST" action="test">
<div class="slidecontainer">
value1
<input type="range" min="1" max="100" value="50" class="slider" name="slider1">
</div>
</form>
<img src="{{ url_for('output_photo') }}" width="300" height="300" alt="" class="img-thumbnail">
I also have an image processing function that runs when the page loads.
#app.route('/output_photo')
def output_photo():
before_img = cv2.imread('images/1.jpg')
result = before_img.copy()
imgray = cv2.cvtColor(before_img, cv2.COLOR_BGR2GRAY)
filtered = cv2.bilateralFilter(imgray, 11, 50, 100)
output_img = filtered
retval, buffer = cv2.imencode('.png', output_img)
response = make_response(buffer.tobytes())
response.headers['Content-Type'] = 'image/png'
return response
What I need
For example in the filtering method(cv2.bilateralFilter) we have parameters that will need to be changed by the sliders (in this case, it is 11,50,100), but at the same time, this method must have default values so that the image is still processed when the page loads.
How can I that?I will be grateful for the answer
You have to declare the method with the route and then you can access the form data through request.form.get('#ID_NAME')
You'll need both flask and request from flask when importing too.
So, something like this..
#app.route('/edit_img', methods=["POST"])
def edit_img():
img_id = request.form.get('id')
### YOUR CODE
return render_template(# the page and data your rendering)
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("/")
This is my sample HTML file
<html>
<head>
<title>
</title>
</head>
<body>
<form action="">
Value a:<br>
<input type="text" name="Va">
<br>
Value b:<br>
<input type="text" name="Vb">
<br><br>
<input type="submit">
</form>
<textarea rows="4" cols="10">
</textarea>
<p>
</p>
</body>
</html>
And a given template Tornado server code:(I also need help on the explanation of each section of the following code)
import tornado.ioloop
import tornado.web
import tornado.httpserver
import tornado.gen
import tornado.options
tornado.options.parse_command_line()
class APIHandler(tornado.web.RequestHandler):
#tornado.web.asynchronous
def get(self):
self.render('template.html')
#tornado.gen.engine
def post(self):
try:
num = int(self.get_argument('num'))
except:
num = 5
self.render('template.html')
app = tornado.web.Application([(r"/next_rec",APIHandler),])
if __name__ == "__main__":
server = tornado.httpserver.HTTPServer(app)
server.bind(48763)
server.start(5)
tornado.ioloop.IOLoop.current().start()
and finally my python code:
if __name__ == '__main__':
a = int(raw_input())
b = int(raw_input())
print a+b
I am using a simple 'a+b' function to test out this feature. But my problem is I can't figure out a way to link them together. So my ultimate goal is to click on the "Submit" button on the HTML, pass on two values to the Tornado server, use it as input in my python script and finally show the output in the text area of the HTML or on another page. I'm know there are tons of information on the web, but I'm completely new to Tornado (near 0 knowledge) and most of them I can't really understand. Help on methods or keywords for search is much appreciated, thank you very much. (please keep answers as basic as possible, it will help a lot, thanks!)
First of all you should check the official documentation. It is quite simple and it targets the newcomers.
Also in this short guide, the sections of a similar code as your is being explained with simplicity.
Now for your code:
On your template you need to specify that the form should send a post request on submit by adding <form method="post" id="sum_form">
Also you need to make sure that you will be submit the data added in the form on an event: $("#sum_form").submit();
On your post method you need to read the passed numbers from your client's form, add them and then send them back to the template as a parameter.
For example:
def post(self):
numA = int(self.get_argument('Va'))
numB = int(self.get_argument('VB'))
sumAB = numA + numB
self.render('template.html',sumAB=sumAB)
In you template.html you need to add a field where you will display the passed sum as a jinja variable : {{sumAB}}
I'm working with an IP camera. I can use a URL such as this one to grab a static image off the camera:
http://Username:Password#IP_of_Camera:Port/streaming/channels/1/picture
What I want to do is have python/flask download the image from that URL when the client loads the page, and embed the image into the page using an img tag.
If I have a template that looks something like this:
<html>
<head>
<title>Test</title>
</head>
<body>
<img src="{{ image }}">
</body>
</html>
how do I replace the {{ image }} with the downloaded image?
Would I use urllib/requests to download the image to flask's static folder, replace {{ image }} with something like {{ url_for('static', filename="temp_image.png") }}, and then delete the image from the static folder when the page loads? Would I download it someplace else instead (other than the static folder)? Or is there some other way to do it that keeps the image in memory?
PS. I know it's possible to replace {{ image }} with that URL directly, but that reveals the username/password/IP/port of the camera to the client.
I would add a masking route on flask that fetches and serves the image directly.
Lets say domain.com/image/user1/cam1
Your server would typically make a http request to the camera and once it receives a response, you can straight up serve it as a Response object with appropriate mimetype.
In this case, the image you fetched from camera resides in your RAM.
#app.route('image/<userID>/<camID>')
def fun(userID,camID):
# fetch the picture from appropriate cam
pic = requests.get('http://'+
'Username:Password'+ # dynamically replace user id / password/ auth
'#IP_of_Camera:Port'+ #dynamically replace port / IP
'/streaming/channels/1/picture')
# do processing of pic here..
return Response(pic,mimetype="image/png")
However, if this image needs to be served over and over again, then you might wanna cache it. In which case, I would pick something closer to your approach.
If you want to stream the camera images, it is a whole different ballgame.
import requests
url = "http://Username:Password#IP_of_Camera:Port/streaming/channels/1/picture"
response = requests.get(url)
if response.status_code == 200:
f = open("/your/static/dir/temp.png", 'wb')
f.write(response.content)
f.close()
{{ url_for('static' filename="temp.png") }}
Not sure why you would need to delete it, but I guess you could if you thought that was required
I have exactly the same problem as this post
Python submitting webform using requests
but your answers do not solve it. When I execute this HTML file called api.htm in the browser, then for a second or so I see its page.
Then the browser shows the data I want with the URL https://api.someserver.com/api/ as as per the action below. But I want the data written to a file so I try the Python 2.7 script below.
But all I get is the source code of api.htm Please put me on the right track!
<html>
<body>
<form id="ID" method="post" action="https://api.someserver.com/api/ ">
<input type="hidden" name="key" value="passkey">
<input type="text" name="start" value ="2015-05-01">
<input type="text" name="end" value ="2015-05-31">
<input type="submit" value ="Submit">
</form>
<script type="text/javascript">
document.getElementById("ID").submit();
</script>
</body>
</html>
The code:
import urllib
import requests
def main():
try:
values = {'start' : '2015-05-01',
'end' : '2015-05-31'}
req=requests.post("http://my-api-page.com/api.htm",
data=urllib.urlencode(values))
filename = "datafile.csv"
output = open(filename,'wb')
output.write(req.text)
output.close()
return
main()
I can see several problems:
Your post target URL is incorrect. The form action attribute tells you where to post to:
<form id="ID" method="post" action="https://api.someserver.com/api/ ">
You are not including all the fields; type=hidden fields need to be posted too, but you are ignoring this one:
<input type="hidden" name="key" value="passkey">
Do not URL-encode your POST variables yourself; leave this to requests to do for you. By encoding yourself requests won't recognise that you are using an application/x-www-form-urlencoded content type as the body. Just pass in the dictionary as the data parameters and it'll be encoded for you and the header will be set.
You can also stream the response straight to a file object; this is helpful when the response is large. Switch on response streaming, make sure the underlying raw urllib3 file-like object decodes from transfer encoding and use shutil.copyfileobj to write to disk:
import requests
import shutil
def main():
values = {
'start': '2015-05-01',
'end': '2015-05-31',
'key': 'passkey',
}
req = requests.post("http://my-api-page.com/api.htm",
data=values, stream=True)
if req.status_code == 200:
with open("datafile.csv", 'wb') as output:
req.raw.decode_content = True
shutil.copyfileobj(req.raw, output)
There may still be issues with that key value however; perhaps the server sets a new value for each session, coupled with a cookie, for example. In that case you'd have to use a Session() object to preserve cookies, first do a GET request to the api.htm page, parse out the key hidden field value and only then post. If that is the case then using a tool like robobrowser might just be easier.
I'm trying to save a chart by converting SVG to PNG with a Python script.
So I start storing the svg data in a variable with :
var svgdata = Ext.draw.engine.SvgExporter.generate(chart.surface);
When I do alert(svgdata), I can see that this output is correct.
But when I send it to the server like this :
Ext.draw.engine.ImageExporter.defaultUrl = "data/svg_to_png.py?svgdata="+svgdata;
The svgdata that has been sent looks like this :
<?xml version=
I'm new to extjs, please help me on this one. What is the right way to send svg data to my python script and render a png image ?
This is my python script :
import cairo
import cgi
import rsvg
print "Content-type: image/png\n\n"
arguments = cgi.FieldStorage()
img = cairo.ImageSurface(cairo.FORMAT_ARGB32, 640,480)
ctx = cairo.Context(img)
handler= rsvg.Handle(None, str(arguments["svgdata"]))
handler.render_cairo(ctx)
img.write_to_png("svg.png")
HELP ME PLEASE!
<div style="display:none;">
<iframe id="file_download_iframe" src="blank.html"></iframe>
</div>
You will need a blank html page on your server for this to work properly in all browsers. Basically the blank.html page is an empty page to satisfy that the ifram always has a page in it.
Then you need a basic form hidden somewhere too:
<div style="display:none;">
<form
id = "file_download_iframe_form"
name = "file_download_iframe_form"
target = "file_download_iframe"
method = "post"
action = "data/svg_to_png.py"
>
<input type="hidden" id="svgdata" name="svgdata"/>
</form>
</div>
Then have a javascript function like this:
function getImage(svgdata){
var form = document.getElementById("file_download_iframe_form");
document.getElementById("svgdata").value = svgdata;
form.submit();
};