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>
Related
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
hi im trying to get access token for my application but i have a problem with executing an api call inside my "profile_token" django view
because i want to execut the call only if the template coresspanding to this view is called,
otherwise it keeps breaking the server because the user should first sign in to ebay then i can make this call
thank you for your help
here is a sample of the code
api = Connection(config_file='ebay.yaml', domain='api.sandbox.ebay.com', debug=True)
url_vars = {'SignIn&RuName': RuName, 'SessID': SessionID}
url = 'https://signin.sandbox.ebay.com/ws/eBayISAPI.dll?'
constructed_url=(url + urllib.parse.urlencode(url_vars))
final_url=urllib.parse.unquote(constructed_url)
def profile(request):
context={
'final_url':final_url
}
return render(request,'users/profile.html',context)
request= {
'SessionID': SessionID
}
# i tried this
def profile_token(request):
response = api.execute('FetchToken', request)
return render(request, 'users/profile_token.html')
# and this
def profile_token(request):
if profile_token:
response = api.execute('FetchToken', request)
return render(request, 'users/profile_token.html')
i guess every time i post a question in here i find the answer by my self
so the mistake was the word 'request ' i should use 'r' or anything else other then 'request' because it is already reserved by the django view function
good luck
def profile(request):
RuName= 'driss_aitkassi-drissait-crm-SB-ijuzzy'
r= {
'RuName': RuName
}
response = api.execute('GetSessionID', r)
print(response)
res =response.text
tree= ET.fromstring(res)
for node in tree.iter('{urn:ebay:apis:eBLBaseComponents}GetSessionIDResponse'):
SessionID= node.find('{urn:ebay:apis:eBLBaseComponents}SessionID').text
print(SessionID)
url_vars = {'SignIn&RuName': RuName, 'SessID': SessionID}
url = 'https://signin.sandbox.ebay.com/ws/eBayISAPI.dll?'
constructed_url=(url + urllib.parse.urlencode(url_vars))
final_url=urllib.parse.unquote(constructed_url)
print(final_url)
context={
'final_url':final_url
}
return render(request,'users/profile.html',context)
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.
This is my github repository for this live demo I have going on at the moment.
//index.js is where the POST request is being sent from
class Index extends React.Component {
state = {
loading: false,
};
handleClickLoading = () => {
this.setState(state => ({
loading: true,
}));
var jqXHR = $.ajax({
type: "POST",
url: "http://localhost:5000/login",
async: true,
data: { mydata: [Cookies.get('links'), Cookies.get('numSentences')] },
success: function(){
const data = JSON.parse(jqXHR.responseText);
console.log(data);
}
});
Cookies.set('final', jqXHR.responseText);
console.log(jqXHR.responseText)
};
render() {
const {loading} = this.state;
return (
<div>
<AppBar/>
<Block/>
<Card>
<CardActions>
<Button size="large"
fullWidth={true}
onClick={this.handleClickLoading}>Submit</Button>
</CardActions>
</Card>
<Fade
in={loading}
unmountOnExit
>
<BottomBar/>
</Fade>
</div>
)
}
}
export default Index;
and its trying to get data ran through python scripts through a Flask server:
...
def crossdomain(origin=None, methods=None, headers=None,
max_age=21600, attach_to_all=True,
automatic_options=True):
if methods is not None:
methods = ', '.join(sorted(x.upper() for x in methods))
if headers is not None and not isinstance(headers, list):
headers = ', '.join(x.upper() for x in headers)
if not isinstance(origin, list):
origin = ', '.join(origin)
if isinstance(max_age, timedelta):
max_age = max_age.total_seconds()
def get_methods():
if methods is not None:
return methods
options_resp = current_app.make_default_options_response()
return options_resp.headers['allow']
def decorator(f):
def wrapped_function(*args, **kwargs):
if automatic_options and request.method == 'OPTIONS':
resp = current_app.make_default_options_response()
else:
resp = make_response(f(*args, **kwargs))
if not attach_to_all and request.method != 'OPTIONS':
return resp
h = resp.headers
h['Access-Control-Allow-Origin'] = origin
h['Access-Control-Allow-Methods'] = get_methods()
h['Access-Control-Max-Age'] = str(max_age)
if headers is not None:
h['Access-Control-Allow-Headers'] = headers
return resp
f.provide_automatic_options = False
return update_wrapper(wrapped_function, f)
return decorator
#app.route("/")
def home():
return "hi"
#app.route("/index")
#app.route('/login', methods=['GET', 'POST', 'OPTIONS'])
#crossdomain(origin='*')
def login():
message = None
if request.method == 'POST':
datafromjs = request.form['mydata']
result = "test"
resp = make_response('{"response": '+result+'}')
resp.headers['Content-Type'] = "application/json"
resp.headers.add('Access-Control-Allow-Origin', '*')
resp.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
resp.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
return resp
return render_template('login.html', message='')
if __name__ == "__main__":
app.run(debug = True)
And this is the console output onClick from the browser:
and Flask:
The javascript is trying to fetch the output of a few python functions given a few parameters.
I'm just at an impasse here and it's the last cog in my project. I have no prior experience with this kind of stuff but any help is appreciated!
I believe this is a CORS issue, like JJ Hakala points out. Even if you are going to the same domain (localhost) but on a different port (8080 -> 5000) then you need an authorisation header to be present (server side).
If you can ensure that the header access-control-allow-origin:* is present (a wildcard domain approach) in server responses, then you should have no more ajax issues.
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
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.