reload html elements flask - python-3.x

Hello everyone!,
so I was building a flask app that displays the current time.The time does display on the webpage as intended.But,the thing is that I have the reload the page manually for the time to update.But I want the time to update on itself.Here is my python file containing the code to the website:
from flask_sqlalchemy import SQLAlchemy
import time
from flask import render_template , Flask
app = Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = True
#app.route('/')
def index():
while True:
global time
time1 = time.time()
global time2
time2 = time.ctime(time1)
return render_template('index.html' , time3 = time2)
if __name__ == '__main__':
app.run(debug = True)
and here is my HTML code for the website:
<!DOCTYPE HTML>
<head>
</head>
<body>
<h1>{{time3}}</h1>
</body>
Can anyone help me out plz?

As I know, you can't do this only using html and python, you need to use Javascript or any other client side language. If time info will be served by python(from server) you can do it like ;
Html and JavaScript code:
<!DOCTYPE HTML>
<html>
<body>
<h>Time: </h>
<span id="time"></span>
</body>
<script type=text/javascript>
function timeClock()
{
var xhr = new XMLHttpRequest();
xhr.open("GET", "{{ url_for('time_info') }}", true);
xhr.onload = function()
{
if(this.status = 200)
{
time.innerHTML = this.response;
}
else
{
console.error(xhr);
}
};
xhr.send(null);
}
setInterval(timeClock, 1000);
</script>
</html>
Flask code:
from flask import Flask,render_template,jsonify
import time
app = Flask(__name__)
#app.route("/")
def main_page():
return render_template("index.html")
#app.route("/time_info",methods=['GET'])
def time_info():
return jsonify(time.ctime())
if __name__ == "__main__":
app.run(debug=True)
timeClock() func will send GET reqest to the server every second and python will get this request and it will send time.ctime() output to the client. Client will get this info and then it will update the html span element

Related

Restful API tutorial (unable to get an alert on localhost)

I am doing a Flask tutorial for a Restful API and am trying to make the stores variable appear as an alert on the homepage using the following syntax in both files.
Any ideas on why I can't seem to get the alert to pop up in the browser whenever I go to localhost ?
Additionally, I have been told by Stack Overflow that my post does not contain enough words so I am typing more words here.
main.py file
from flask import Flask, jsonify, request, render_template
app = Flask(__name__)
stores =[
{
'name':'The Best Store',
'items':[
{
'name': 'Air Jordans',
'price': 16.99
}
]
}
]
#simulating an online store
#app.route('/')
def home():
return render_template('index.html')
#app.route('/store', methods=['POST'])
def create_store():
request_data = request.get_json() #function for handling request from browser to add post request
new_store = {
'name': request_data['name'],
'items': []
}
stores.append(new_store)
return jsonify(new_store)
#app.route('/store/<string:name>')
def get_store(name): #function to check through existing store names and print error if already found in DB ß
for store in stores:
if store['name'] == name:
return jsonify(store)
return("store not found")
#app.route('/store')
def get_stores():
return jsonify({'stores':stores}) #the stores variable above is a list. We need to make iti nto a dictionary for jsonify to turn into a Json.
#app.route('/store/<string:name>/item', methods=['POST'])
def create_item_in_store(name): #check to see if the post method is equal to a store and the append the new names / prices
for store in stores:
request_data = request.get_json()
if store['name'] == name:
new_item = {
'name': request_data['name'],
'price': request_data['price']
}
store['items'].append(new_item)
return jsonify(new_item)
return jsonify({'message': 'store not found'}) #make sure this is outside of the loop ... obvious reasons
#app.route('/store/<string:name>/item')
def get_items_in_store(name):
for store in stores:
if store['name'] == name:
return jsonify({'items': store['items']})
return jsonify({'message': 'store not found'})
app.run(port=5000)
app.debug=True
index.html file
<html>
<head>
<script type="text/javascript">
function httpGetAsync(theUrl, callback) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
callback(xmlHttp.responseText);
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.send(null);
}
httpGetAsync('http://127.0.0.1:5000/store', function() {
alert(response);
})
</script>
</head>
<body>
<div id="myElement">
Hello, world!
</div>
</body>
</html>

background task does not emit

There are many tutorials available for Flask and SocketIO, I could not find any for a simple threaded approach that I understood. But I did read and followed many of them.
I'd like to show my Python application on a web page using websockets so it's kind-of real-time monitoring. This is me trying to understand how to implement this.
The code I currently have is working for except the emit part. There does not seem to be any transfer of data. I'd like to know why.
The socket.on('tingeling' ... is not being triggered.
My Python code, mostly taken from https://codeburst.io/building-your-first-chat-application-using-flask-in-7-minutes-f98de4adfa5d
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = ''
socketio = SocketIO(app)
thread = None
def counter():
print("counter ding")
counting = 0
while True:
counting += 1
socketio.sleep(2)
socketio.emit('tingeling', counting, namespace='')
print(f"Counter: {counting}")
#app.route('/')
def sessions():
print('route')
return render_template('index.html')
#socketio.on('my event')
def connected(data):
print('my event')
#socketio.on('connect')
def starten():
print("connect")
socketio.emit('tingeling', 'start')
global thread
if thread is None:
print('thread ding')
thread = socketio.start_background_task(target=counter())
return render_template('index.html')
if __name__ == '__main__':
socketio.run(app, debug=True)
And my HTML template:
<!DOCTYPE html>
<html lang="en">
<head>
<title>fristi</title>
</head>
<body>
<h3 style='color: #ccc;font-size: 30px;'>waiting</h3>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.min.js"></script>
<script type="text/javascript">
var socket = io.connect('http://' + document.domain + ':' + location.port);
console.log('doet iets')
socket.on( 'connect', function() {
socket.emit( 'my event', {
data: 'User Connected'
})
})
socket.on('tingeling', function(msg) {
console.log('iets komt binnen')
console.log(msg)
})
</script>
</body>
</html>
My error is on the line: thread = socketio.start_background_task(target=counter())
There I reference the function to run as a background task but I use the notation with () and that is not allowed because is runs the function and does not provide the start_background_task with a reference to this function.

Getting a 500 Internal Server error while posting data via Ajax to Flask [duplicate]

This question already has answers here:
How to get POSTed JSON in Flask?
(13 answers)
Closed 4 years ago.
I previously posted this code for a different error, but I am getting a new error after that, so posting in a new post.
I have a basic Flask app, that logs user-agent strings and users local clock times in a database. My template file (templates/home.html) is as follows:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type=text/javascript>
$(document).ready(function () {
console.log('Date Being Posted');
var clock = new Date();
console.log(JSON.stringify(clock));
$.ajax({
url:"/home",
clock: JSON.stringify(clock),
type:'POST',
success: function(response){
console.log(response);
},
error: function(error){
console.log(error);
}
});
});
</script>
</head>
<body>
<p>Your clock is being recorded on the loading of the webpage!</p>
{% for user in users %}
<p>{{user.clock}}</p>
{% endfor %}
</body>
</html>
And my main.py is as follows:
import os
from flask import Flask
from flask import render_template
from flask import request
from sqlalchemy import exc
from flask_sqlalchemy import SQLAlchemy
project_dir = os.path.dirname(os.path.abspath(__file__))
#path to the database
database_file = "sqlite:///{}".format(os.path.join(project_dir, "userdatabase.db"))
app = Flask(__name__)
#indicate to the web application where the database will be stored
app.config["SQLALCHEMY_DATABASE_URI"] = database_file
#initialize a connection to the database; use the db variable to interact with the databse
db = SQLAlchemy(app)
##define a model for the user
class User(db.Model):
user_id = db.Column(db.Integer, primary_key=True)
user_agent = db.Column(db.String(1024), index=True)
clock = db.Column(db.String(1024), index=True)
def __repr__(self):
return "<User-Agent: {}, Clock: {}".format(self.user_agent, self.clock)
#app.route("/home", methods=["GET", "POST"])
def home():
if request.method == "POST":
user_agent_received = request.headers.get('User-Agent')
clock_received = request.json['clock']
user = User(user_agent=user-agent_received, clock=clock_received)
print (user)
try:
db.session.add(user)
db.session.commit()
except exc.IntegrityError as e:
db.session().rollback()
users = User.query.all()
return render_template("home.html", users=users)
if __name__ == "__main__":
app.run(debug=True)
Over here, I am:
a) initializing the database and creating a Model for the Users
b) receiving the clock times posted via ajax request inside home.html and storing it inside the database, while at the same time sending it to the home.html page to be displayed.
The database was created separately on the Python3 Interpretor.
However, on the server, I am getting a 500 Internal Server error. This error is displayed on the console, while I try to look inside Dev Tools to figure out the causes. I can't figure out why this could be the case, could anyone please help?
Firstly, ajax post in jquery has this structure:
var clock={
"key":value //say
};
$.ajax({
url: 'home',
type: 'POST',
dataType: 'json',
data: JSON.stringify(clock),
contentType:"application/json; charset=UTF-8"
})
.done(function(data) {
// do stuff here
})
.fail(function(err) {
// do stuff here
})
.always(function(info) {
// do stuff here
});
Now to access a posted JSON in flask, it's extremely simple use of get_json() method as:
#app.route("/home", methods=["GET", "POST"])
def home():
if request.method == "POST":
user_agent_received = request.get_json()
# user_agent_received is now a regular
# python dictionary with same structure
# as input json sent from jQuery on client.

Flask-socketio sending payloads one at a time

I have the following Python script which is using Flask-socketio
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
from time import sleep
app = Flask(__name__)
app.config['SECRET_KEY'] = 'P#ssw0rd'
socketio = SocketIO(app)
#app.route('/')
def index():
return render_template('index.html')
#socketio.on('connect')
def on_connect():
payload1 = 'Connected!!!'
payload2 = 'Doing thing 1'
payload3 = 'Doing thing 2'
emit('send_thing', payload1, broadcast=True)
sleep(2)
emit('send_thing', payload2, broadcast=True)
sleep(2)
emit('send_thing', payload3, broadcast=True)
if __name__ == '__main__':
socketio.run(app)
And here is the corresponding index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SocketIO Python</title>
</head>
<body>
<div id="my-div"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.5/socket.io.js"></script>
<script>
(function init() {
var socket = io()
var divElement = document.getElementById('my-div')
socket.on('send_thing', function(payload) {
var dataElement = document.createElement('inner')
dataElement.innerHTML = payload
divElement.appendChild(dataElement)
})
})()
</script>
</body>
</html>
What I am trying to achieve is that when a client connects, it first says 'Connected!!!' and then 2 seconds later a new 'inner' element appears that says 'Doing thing 1' followed by 2 seconds later a new 'inner' element appears that says 'Doing thing 2' etc.
But what is happening is that when a client connects, it sends all 3 lines at the same time (after 4 seconds which is both sleep statements). This is the first time using SocketIO so I'm sure I've done something wrong.
When you use eventlet or gevent, the time.sleep() function is blocking, it does not allow any other tasks to run.
Three ways to address this problem:
Use socketio.sleep() instead of time.sleep().
Use eventlet.sleep() or gevent.sleep().
Monkey patch the Python standard library so that time.sleep() becomes async-friendly.

D3.js with Python, rendering a blank page

Setup: I'm trying to create a simple D3 js demo with Python 3 handling requests. Following the steps below I expected to see an error or some kind of HTML generated when I click on my html page with my d3 method. Instead, I receive a blank page.
1) Create custom HTTPRequestHandler class to handle GET requests
from http.server import BaseHTTPRequestHandler, HTTPServer
import os
class HTTPRequestHandler(BaseHTTPRequestHandler):
#handle GET command
def do_GET(self):
rootdir = r'C:\Current_Working_Directory' #file location
try:
if self.path.endswith('.json'):
f = open(rootdir + self.path, 'rb') #open requested file
#send code 200 response
self.send_response(200)
#send header first
self.send_header('Content-type','applicaon/json')
self.end_headers()
#send file content to client
self.wfile.write(f.read())
f.close()
return
except IOError:
self.send_error(404, 'file not found')
def run():
print('http server is starting...')
#ip and port of server
server_address = ('127.0.0.1', 80)
httpd = HTTPServer(server_address, HTTPRequestHandler)
print('http server is running...')
httpd.serve_forever()
if __name__ == '__main__':
run()
2) Save above file as server.py and run python server.py and create some dummy json data stored in data.json in $rootdir and create d3.html:
<!DOCTYPE html>
<html>
<head>
<title>D3 tutorial 10</title>
<script src=”http://d3js.org/d3.v3.min.js”></script>
</head>
<body>
<script>
d3.json(“dummy.json”, function (error,data) {
if (error) return console.warn(error);
console.log(data)
});
</script>
</body>
</html>
4) Open up web page expecting to see an error or some indication that d3 has sent the GET request to the server, but get a blank page.

Resources