Reputation: 73
I am new to flask and web development. I want to display an image on a local web server after I press a button on the webpage. I am using Flask.Ive been trying to figure this out for a while and havent been able too so any help would be incredible. FLASK CODE:
@app.route('/graph_select')
def graph_select():
return render_template('live_stream.html')
@app.route('/read_ph', methods=["GET"])
def ph_plot():
if request.method == "GET":
all_plots.ph_plot()
return render_template('live_stream.html')
@app.route("/read_temp", methods=["GET"])
def temp_plot():
if request.method == "GET":
all_plots.temperature_plot()
return render_template('live_stream.html')
@app.route('/read_distance', methods=["GET"])
def distance_plot():
if request.method == "GET":
all_plots.distance_plot()
return render_template('live_stream.html')
HTML CODE:
<h1>Data Monitoring Station</h1>
<form method="GET"
<a href="read_temp"><button type="button">Temperature Graph</button></a>
<a href="read_ph"><button type="button">PH Graph</button></a>
<a href="read_distance"><button type="button">Distance Graph</button></a>
</form>
<h3><img src="{{ url_for('static', filename='ph_plot.png') }}" width="30%">$
<h3><img src="{{ url_for('static', filename='temperature_plot.png') }}" width="30%">$
<h3><img src="{{ url_for('static', filename='distance_plot.png') }}" width="30%">$
</body>
</html>
Upvotes: 3
Views: 6105
Reputation: 1387
Here's a more complete, end to end solution.
Let's say you want to do a reactive "Check" or "Like", where you click a Check/Thumbs up icon, and you want it to change its appearance immediately in some way (in this case by changing the img src) AND persist that click with the record. (this is obviously required if you want to retain whatever state the click set, so that it will be reflected upon subsequent viewing)
In our use case we're going to indicate if a record has been reviewed. If not, show an empty circle image, if so, show a circle image with a green checkmark in the middle. We'll use Mongo for our backend.
Jinja Template Fragment
<dt class="col-sm-4">Reviewed</dt>
<dd class="col-sm-7"><img src="{{ initialImgSrc }}" id="circle_img" alt="{{ dnote.id}}"/></dd>
Notes:
dnote.id
) in the img as alt text so we can access it easily in our JavaScript function in order to pass it to the Flask functionJavaScript
<script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous"></script>
<script type="text/javascript">
var thisImg = document.getElementById("circle_img");
$(document).ready(function () {
$('#circle_img').bind('click', function () {
$.getJSON('/review/circler', {
currentCircle: thisImg.getAttribute('src'),
dNoteID: thisImg.getAttribute('alt'),
}).done(function (data) {
thisImg.src=data.imgSrcHTML;
})
return false;
});
});
</script>
Notes:
<meta id="dNoteIDforJS" data-name="{{ dnote.id }}">
then refer to that in JS with $('#dNoteIDforJS').data("name")
getJSON('/review/circler
, we're using a blueprint with a url prefix of review
and our function is called circler
Flask Function
@review_blueprint.route("/circler")
def circler():
currentCircle = request.args.get('currentCircle', type=str)
dNoteID = request.args.get('dNoteID', type=str)
thisDNote = Mongo_DNotes.objects.get(id=dNoteID)
eq = thisDNote.DNoteEngagementsQty
try:
engagementsQty = int(eq)
except:
engagementsQty = 0
# Since we clicked, we can advance now
engagementsQty += 1
imgSrcHTML = "/static/circles/{}/circle_checked.png".format(engagementsQty)
thisDNote.DNoteEngagementsQty = engagementsQty
thisDNote.save()
return jsonify(imgSrcHTML=imgSrcHTML, currentCircle=currentCircle)
Notes:
getJSON
is going to have to return something like jsonify(imgSrcHTML=imgSrcHTML, currentCircle=currentCircle)
if that getJSON has references to data.imgSrcHTML
One more thing
If you want to make sure your image exists and you're using blueprints, you can check it with:
os.path.exists(os.path.join(review_blueprint.static_folder, "circles/{}/circle_checked.png".format(engagementsQty)))
. In my use case, this lets you handle when the number of reviews have maxed out. I believe you also need to explicitly set the static_folder argument in Blueprint() as well. (I like blueprints, but they do present you with the occasional gotcha)
CAVEAT From the Flask docs:
fetch() is the modern, built-in JavaScript solution to making requests from a page. You may have heard of other “AJAX” methods and libraries, such as XMLHttpRequest() or jQuery. These are no longer needed in modern browsers, although you may choose to use them or another library depending on your application’s requirements.
I have subsequently used fetch() and it is indeed the modern way to go - in particular for invoking async functions and using toasts to communicate results to users.
https://flask.palletsprojects.com/en/2.3.x/patterns/javascript/
Upvotes: 0
Reputation: 6017
TLDR;
I wrote a minimal example on displaying images on button click using Flask
and Ajax
.
In essence, I just returned the URL of the image to the HTML page and set the src
attribute of <img>
tag with the returned URL.
app.py:
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def hello():
return render_template('a.html')
@app.route("/getimage")
def get_img():
return "a.jpg"
if __name__ == '__main__':
app.run()
a.html:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<body>
<button type='button' id ='retrieve'>Submit</button>
<img src="" id="myimg" />
</body>
<script>
$(document).ready(function() {
$('#retrieve').click(function(){
$.ajax({
url: "{{ url_for ('get_img') }}",
type: "GET",
success: function(response) {
$("#myimg").attr('src', '/static/' + response);
},
error: function(xhr) {
//Do Something to handle error
}
});
});
});
</script>
</html>
You can modify this code as you wish.
Note: The a.html file should be in templates
folder and the a.jpg file should be in the static
folder.
Hope this helps. Good luck.
Upvotes: 5