I'm working on Flask and I'm stuck in a strange situation.
I'm trying to change an image with javascript but flask gives me these errors:
... 12:05:34] "GET / HTTP/1.1" 200 -
... 12:05:38] "GET /img/immagine.jpg HTTP/1.1" 404 -
JS:
var btnAddImage = document.getElementById("btnAddImage");
btnAddImage.onclick = function() {
var img = document.createElement("img");
img.src = "/static/img/immagine.jpg.jpg";
document.getElementById("asi").appendChild(img);
};
As you can see in the path it's specified as static but it's not read.
I'm using the simply render_template method:
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
def hello():
return render_template('index.html', nome=nome)
enter code here
The error message clearly states that the image could not be found.
Your code does not match the error message. One time you have .jgp as file ending, one time .jpg.jpg.
Try to compare the image name and path with the one you write in your code.
If you cannot figure out how to fix this, please also give us an overview of your directory structure.
Related
I am new to web programming.
Writing a simple ajax call to run a python function via 2 files
javascriptPython3.html & javascriptPython3.py
Client is a macbook & firefox 80.0.1
Webserver is a raspberry pi Apache/2.4.25 (Raspbian) Server at rbp Port 80
On the server I run:
export FLASK_DEBUG=1
export FLASK_APP=javascriptPython3.py
flask run -h 192.168.1.6
* Serving Flask app "javascriptPython3"
* Forcing debug mode on
* Running on http://192.168.1.6:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger pin code: 318-477-733
192.168.1.3 - - [10/Dec/2022 14:44:55] "GET / HTTP/1.1" 200 -
192.168.1.3 - - [10/Dec/2022 14:44:57] "GET / HTTP/1.1" 200 -
192.168.1.3 - - [10/Dec/2022 14:44:58] "GET / HTTP/1.1" 200 -
On the client macbook browser:
http://192.168.1.6:5000/
Each Time I reload the webpage, I get an output line in the flask run.
So far so good.
But when I browse to javascriptPython3.html on the client, and click the button, I get 404 not found in the browser console.
If I change the ajax url to "javascriptPython3.py" I get 500 Internal Server error.
#!/usr/bin/env python3
#from flask import Flask, request, render_template
from flask import Flask
app = Flask(__name__)
#app.route('/', methods=['GET','POST'])
def makeupper():
# javascriptdata=request
# javascriptdata=javascriptdata.upper()
outputfile = open("javascriptPython.out", "a")
outputfile.write("Hello from Python\n\n")
return "ABCCC"
javascriptPython3.html:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
function successFun(pythonResponse) {
window.alert(pythonResponse);
document.getElementById('output1').value = pythonResponse;
}
function runPython() {
window.alert("We just called runPython()");
$.ajax({
type: "POST",
url: "/javascriptPython3.py",
// url: "/",
// data: "abc",
success: successFun()
});
}
</script>
</head>
<body>
<p> run python from javascrpt </p>
<br>
<input type="button" onClick="runPython()" value="Run Python" />
<br>
<br>
<p> Output text </p>
<textarea id="output1" rows="4" cols="50"> </textarea>
</body>
</html>
I was expecting to see javascriptPython.out get appended everytime
I clicked the button.
It got appended when I kept reloading http://192.168.1.6:5000/ just as I wanted it to
But when I browse to javascriptPython3.html on the client
That is correct. In your code, there is no route for javascriptPython3.html
A very high level/simplistic explanation
Flask returns (serves up) content based on paths (routes) you have defined in your python code. It can return content as plain text or it can return the content via a template (html page) i.e. render_template(<html_page>)
In your code, you have only defined one route - #app.route('/' which corresponds to http://192.168.1.6:5000/ . Think of it this way - anything you have defined in as a route comes after your server address which is http://192.168.1.6:5000
If you want to navigate to javascriptPython3.html i.e. you want to be able to type the url http://192.168.1.6:5000/javascriptPython3.html, then you have to define a route for it in your code i.e. you need something like app.route('/javascriptPython3.html')
Since it looks like you want to display javascriptPython3.html when you open your server (i.e when you go to your root i.e. /), you should modify your existing code to
from flask import Flask, request, render_template
app = Flask(__name__)
#app.route('/', methods=['GET','POST'])
def makeupper():
outputfile = open("javascriptPython.out", "a")
outputfile.write("Hello from Python\n\n")
return render_template('javascriptPython3.html')
I finally got it working ; Again I was trying to simply route to (run) a python function via ajax call.
I just needed to use a complete URL with IP and port, pointing to the apache server in my html file
AJAX URL: url: "http://192.168.1.9:5000/foo",
python route: #app.route('/foo', methods=['GET','POST'])
Below are the 2 files that work
export FLASK_APP=javascriptPython3.py
export FLASK_DEBUG=1
flask run -h 192.168.1.9
Browse to: http://192.168.1.9/javascriptPython3.html
#!/usr/bin/env python3
from flask import Flask, request, render_template
app = Flask(__name__)
#app.route('/foo', methods=['GET','POST'])
def foo():
# javascriptdata=request
# javascriptdata=javascriptdata.upper()
outputfile = open("javascriptPython.out", "a")
outputfile.write("Hello from Python\n\n")
return "ABCCC"
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.
min.js"></script>
<script>
function successFun(pythonResponse) {
window.alert(pythonResponse);
document.getElementById('output1').value = pythonResponse;
}
function runPython() {
window.alert("We just called runPython()");
$.ajax({
type: "GET",
url: "http://192.168.1.9:5000/foo",
// data: "abc",
success: successFun()
})
}
</script>
</head>
<body>
<p> run python from javascrpt </p>
<br>
<input type="button" onClick="runPython()" value="Run Python" />
<br>
<br>
<p> Output text </p>
<textarea id="output1" rows="4" cols="50"> </textarea>
</body>
</html>
Hello I am having a hard time trying to get my survey app to work. Run I run the flask app it gives me a couple of errors.
Failed to load resource: the server responded with a status of 404 (NOT FOUND) :5000/favicon.ico:1
Failed to load resource: the server responded with a status of 500 (Internal Server Error) :5000/test:1
This is the error in the terminal
Traceback (most recent call last):
File "/Users/tannerormanoski/opt/anaconda3/lib/python3.9/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/Users/tannerormanoski/opt/anaconda3/lib/python3.9/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/tannerormanoski/opt/anaconda3/lib/python3.9/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/tannerormanoski/opt/anaconda3/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/Users/tannerormanoski/opt/anaconda3/lib/python3.9/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/tannerormanoski/opt/anaconda3/lib/python3.9/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/tannerormanoski/Documents/Survey_2/Input_Saving_Test/app.py", line 21, in test
result = json.load(output) # This converts the json output to a python dictionary
File "/Users/tannerormanoski/opt/anaconda3/lib/python3.9/json/__init__.py", line 293, in load
return loads(fp.read(),
AttributeError: 'list' object has no attribute 'read'
127.0.0.1 - - [20/Sep/2022 08:45:15] "POST /test HTTP/1.1" 500 -
127.0.0.1 - - [20/Sep/2022 08:45:45] "GET /test HTTP/1.1" 405 -
This is my app.py
import json
from flask import request
from flask import Flask, render_template
app = Flask(__name__,
static_folder='static',
template_folder='templates')
#app.route('/')
def index():
return render_template('index.html')
#app.route('/test', methods=['POST'])
def test():
output = request.get_json()
print(output) # This is the output that was stored in the JSON within the browser
print(type(output))
result = json.load(output) # This converts the json output to a python dictionary
print(result) # Printing the new dictionary
print(type(result)) # This shows the json converted as a pyhthon dictionary
return result
if __name__ == "__main__":
app.run(debug=True)
This is the snippet from my app.js file
let persons = [];
const addPerson = (ev)=>{
ev.preventDefault(); //stop form from submitting
let person = {
name: document.getElementById("name").value,
title: document.getElementById("title").value,
role: document.getElementById("role").value,
reports: document.getElementById("reportsTo").value,
fact: document.getElementById("funFact").value
}
persons.push(person);
document.forms[0].reset(); // to clear the form for the next entries
//for display purposes only
console.warn('added' , {persons} );
let pre = document.querySelector('#msg pre');
pre.textContent = '\n' + JSON.stringify(persons, '\t', 2);
$.ajax({
url: '/test',
type: "POST",
contentType: "application/json",
data: JSON.stringify(persons)
});
It seems to be where '/test' app route, as in the url in the app.js file it does not underline the link as it normally would. I am newer to coding and very new with flask, so I am having trouble diagnosing the problem myself.
If it helps my file structure is
>static
app.js
style.css
>Images
>templates
index.html
app.py
Your templates folder is expecting only template files (.html files).
It's standard to have your app.py file in the root of your project.
Your structure should look like this. Same w/ your app.js file.
>static
style.css
>Images
>templates
index.html
app.py
app.js
https://flask.palletsprojects.com/en/2.2.x/tutorial/layout/
Edit1:
Also, it may not be valid to return the python dictionary like that.
Try creating a response before returning, I've had to use this when returning pdf files, etc.
from flask import json
#app.route('/test', methods=['POST','GET])
def test():
output = request.get_json()
print(f'output: {output}, output type: {type(output)}')
response = app.response_class(
response=json.dumps(output),
status=200,
mimetype='application/json'
)
return response
reference material:
Return JSON response from Flask view
I run the following flask app on local host. I then hit the app on address/place_job/ with a http request. afterwards i go on my browser and look up address/track_site/job/0
expected behavior: The word "foo" show up immediately.
actual behavior: The browser (edge / Chrome) waits / spins until the thread finishes, and then immediately displays the word foo
Question: Why is the actual behavior happening, instead of the expected behavior, and how do i fix it? Preferably without sorting to celery or the likes.
I don't understand why this happens. What really bugs my mind, is that the expected behavior occurs If i delete the <script> line in the .HTML file. I have tested it with threading.Thread, as well as the threadpool executor from the flask-executor package.
minimal_app.py:
from flask import Flask, render_template
from threading import Thread
from time import time
app = Flask(__name__)
def func():
print("started")
start_time = time()
while time()-start_time<20: pass
print("ended")
#app.route('/place_job/')
def place_job():
Thread(target=func).start()
return "OK"
#app.route('/track_site/job/0')
def track_job():
return render_template('minimal_template.html')
static/templates/minimal_template.html
<!DOCTYPE html>
<html lang="en">
<body>
<h1 id="id1"> Job Page </h1>
<script type="text/javascript" src="/static/js/const.js"></script>
<p id="id2"> foo </p>
</body>
</html>
static/js/const.js
const x = 0;
edit
Below is the flask log after requesting /place_job/ and afterwards navigating to /track_site/job/0 :
127.0.0.1 - - [22/Apr/2022 20:15:04] "GET /place_job HTTP/1.1" 308 -
127.0.0.1 - - [22/Apr/2022 20:15:04] "GET /place_job/ HTTP/1.1" 200 -
started
127.0.0.1 - - [22/Apr/2022 20:15:12] "GET /track_site/job/0 HTTP/1.1" 200 -
ended
127.0.0.1 - - [22/Apr/2022 20:15:24] "GET /static/js/const.js HTTP/1.1" 304 -
I writing an app in Angular + Flask hosted on heroku. I've been looking to use html5mode to use myapp.co/register for oauth. The problem with html5mode is that server needs to rewrite url if someone refreshes the page or clicks the link that is not root. I tried to use this snippet to catch them all, but it doesn't work.
#app.route("/", defaults={"path": ""})
#app.route("/<path:path>")
def index(path):
print path
return make_response(open(app.static_folder + "index.html").read())
output 404
* Restarting with reloader
127.0.0.1 - - [23/Jan/2014 13:41:48] "GET /ass HTTP/1.1" 404 -
App got root that servers index.html and /api/v1/ that is RESTful api
You need to use something more than you have:
#app.route("/", defaults={"path": ""})
#app.route("/<string:path>") <--- this is missing
#app.route("/<path:path>")
def index(path):
print path
return make_response(open(app.static_folder + "index.html").read())
So:
#app.route("/<string:path>")
is missing. It catches string variables (not path), so in your case just ass from your example, when you try to hit http://localhost:5000/ass.
Your code will catch all urls if you do not have any more routes with more highest priority. But look like it should return 500 error (because I hope you do not have <app_path>/staticindex.html and use unsafe method to send file).
So if you have another rules you must look at rule priority (see https://stackoverflow.com/a/17146563/880326).
If you have error with this route better use:
#app.route("/", defaults={"path": ""})
#app.route("/<path:path>")
def index(path)
return send_from_directory(app.static_folder, "index.html")
I want to display my CPU usage dynamically. I don't want to reload the page to see a new value. I know how to get the CPU usage in Python. Right now I render a template with the value. How can I continually update a page with a value from Flask?
#app.route('/show_cpu')
def show_cpu():
cpu = getCpuLoad()
return render_template('show_cpu.html', cpu=cpu)
Using an Ajax request
Python
#app.route('/_stuff', methods= ['GET'])
def stuff():
cpu=round(getCpuLoad())
ram=round(getVmem())
disk=round(getDisk())
return jsonify(cpu=cpu, ram=ram, disk=disk)
Javascript
function update_values() {
$SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
$.getJSON($SCRIPT_ROOT+"/_stuff",
function(data) {
$("#cpuload").text(data.cpu+" %")
$("#ram").text(data.ram+" %")
$("#disk").text(data.disk+" %")
});
}
Using Websockets
project/app/views/request/websockets.py
# -*- coding: utf-8 -*-
# OS Imports
import json
# Local Imports
from app import sockets
from app.functions import get_cpu_load, get_disk_usage, get_vmem
#sockets.route('/_socket_system')
def socket_system(ws):
"""
Returns the system informations, JSON Format
CPU, RAM, and Disk Usage
"""
while True:
message = ws.receive()
if message == "update":
cpu = round(get_cpu_load())
ram = round(get_vmem())
disk = round(get_disk_usage())
ws.send(json.dumps(dict(received=message, cpu=cpu, ram=ram, disk=disk)))
else:
ws.send(json.dumps(dict(received=message)))
project/app/__init__.py
# -*- coding: utf-8 -*-
from flask import Flask
from flask_sockets import Sockets
app = Flask(__name__)
sockets = Sockets(app)
app.config.from_object('config')
from app import views
Using Flask-Websockets made my life a lot easier. Here is the launcher :
launchwithsockets.sh
#!/bin/sh
gunicorn -k flask_sockets.worker app:app
Finally, here is the client code :
custom.js
The code is a bit too long, so here it is.
Note that I'm NOT using things like socket.io, that's why the code is long. This code also tries to reconnect to the server periodically, and can stop trying to reconnect on a user action. I use the Messenger lib to notify the user that something went wrong. Of course it's a bit more complicated than using socket.io but I really enjoyed coding the client side.