My variable won't update when displaying it in HTML. (flask) - python

When i try to display the variable "balance" in my HTML code,it will appear in the page but it won't update when using a function that has to update it,and it keeps returning me the same value (10) when running the app on browser.
<a href="{{ url_for('deposit10')}}" class='btn btn-primary'>10</a>
Balance: {{ balance }}
from flask import Flask, render_template
app = Flask(__name__)
balance=10
..
..
..
#app.route('/home', methods = ['GET', 'POST'])
def deposit10(balance,safe):
if balance>=10:
balance-=10
safe+=10
return render_template("game1.html", balance=balance)
else:
return 0

Related

How do I make an HTML button execute python code onclick?

I’m new to web development. I have learned how to make a web sever using flask. What I want to do is make an html button run python code from the web server when it is clicked. Is this even possible? If so, can someone point me to some html examples that can do that?
Update: I think I found some code that might work with what I’m asking. I don’t know for sure if it would work or not.
Here is the link:
Call a python function within a html file
If I were to convert the “click a link” aspect of the code to “click a button” would it run my python code on the viewers end, not my end?
It is Possible in Two ways
Create an HTML form and button to submit the form. The from can call the post URL on the flask server
Add some javascript to the HTML and call any HTTP method /url that you have created using the flask server.
You can use button with form or with JavaScript
Form
Normally to use button you need <form> which sends request to Flask to url defined in action="..." and Flask sends back response (text/HTML) and browser automatically put it in window in place of previous HTML - so server has to generate full HTML again and again.
from flask import Flask, request, render_template_string
import datetime
app = Flask(__name__)
#app.route('/')
def index():
return render_template_string('''<form action="/page" method="POST">
<button type="submit" name="btn" value="Button 1">Button 1</button>
<button type="submit" name="btn" value="Button 2">Button 2</button>
<button type="submit" name="btn" value="Button 3">Button 3</button>
</form>''')
#app.route('/page', methods=['GET', 'POST'])
def page():
value = request.form.get('btn') # gives text from `value="Button 1"`
return f'You pressed {value} at ' + datetime.datetime.now().strftime('%Y.%m.%d %H:%M.%S')
if __name__ == '__main__':
#app.debug = True
app.run() #debug=True
And the same using empty action="" so it sends request to the same url and it needs to check request.method to run different code
from flask import Flask, request, render_template_string
import datetime
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
value = request.form.get('btn') # gives text from `value="Button 1"`
info = f'You pressed {value} at ' + datetime.datetime.now().strftime('%Y.%m.%d %H:%M.%S')
else:
info = ""
return render_template_string('''<form action="" method="POST">
<button type="submit" name="btn" value="Button 1">Button 1</button>
<button type="submit" name="btn" value="Button 2">Button 2</button>
<button type="submit" name="btn" value="Button 3">Button 3</button>
</form>{{text}}''', text=info)
if __name__ == '__main__':
#app.debug = True
app.run() #debug=True
JavaScript
If you want to execute Flask code without reloading all HTML then you need to use JavaScript which can send request to server using old
XMLHttpRequest or modern fetch(), get response and replace only part of HTML. Often in this method server sends JSON data and JavaScript may use it to replace HTML in different places.
And this method need to learn JavaScript to create something more complex.
from flask import Flask, request, render_template_string
import datetime
app = Flask(__name__)
#app.route('/')
def index():
return render_template_string('''
<button onclick="my_function()">Get Time</button>
<span id="time">Press Button to see current time on server.</span>
<script>
span_time = document.querySelector("#time");
function my_function(){
fetch('/get_time')
.then(res => res.text())
.then(text => span_time.innerHTML = text);
}
</script>
''')
#app.route('/get_time')
def time():
return datetime.datetime.now().strftime('%Y.%m.%d %H:%M.%S')
if __name__ == '__main__':
#app.debug = True
app.run() #debug=True
In examples I use render_template_string instead of render_template to make code simpler - now everyone can copy code and paste to one file and run it.

Internal server error when clicking button in flask app

I'm new to Flask and trying to build my first simple app which takes a text input and upon the user clicking a button I want it to display the text that was entered.
My HTML page loads successfully and I can enter the text into the input.
However, when I click the button I get a new page showing the following error:
Internal Server Error
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
My HTML:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Predict Code</h1>
<form action="http://localhost:5000/predict" method="post">
<label form="description">Description:</label>
<input type="text" id="description" name="description">
<button type="submit">Predict Code</button>
</form>
<br>
<br>
{{ prediction_text }}
</body>
</html>
My flask app .py:
from flask import Flask, request, jsonify, render_template
# create the flask app
app = Flask(__name__)
# what html should be loaded as the home page when the app loads?
#app.route('/')
def home():
return render_template('app_frontend.html')
# define the logic for reading the inputs from the WEB PAGE,
# running the model, and displaying the prediction
#app.route('/predict', methods=['GET','POST'])
def predict():
# get the description submitted on the web page
a_description = request.form.values()
return render_template('Description entered: {}'.format(a_description))
# boilerplate flask app code
if __name__ == "__main__":
app.run(debug=True)
What have I done wrong and how can I fix it?
The problem is here:
#app.route('/predict', methods=['GET','POST'])
def predict():
# get the description submitted on the web page
a_description = request.form.values()
# THIS LINE:
return render_template('Description entered: {}'.format(a_description))
You're trying to render a template, but passing in a string, not a template.
If you want to return just the string, do this:
return 'Description entered: {}'.format(a_description)
If you look at the python error output you will see:
jinja2.exceptions.TemplateNotFound: Description entered: <generator
object MultiDict.values at 0x000001CEEEF83620>
EDIT
To answer the additional comment question. To get the value of the form post you will need to change your line from:
a_description = request.form.values()
to:
a_description = request.form.get('description')

werkzeug.routing.BuildError with Flask -- trying to build a very simple webapp

I'm trying to develop a simple webapp that prompts the user for their address, requests forecast information from the NWS through their API, and prints out the results, but I'm running into some issues tying together the HTML and the Python script. I'm still new to programming in general and this is all a very rough copy at the moment, here's the relevant code:
weather.py:
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def home():
return render_template('weather.html')
#app.route('/forecast', methods=['GET', 'POST'])
def forecast():
if request.method == 'POST':
location = request.form['address']
# gets the weather information
return render_template('forecast.html', varying_forecast = forecast, wfo = wfo_info)
if __name__ == '__main__':
app.run(debug=True)
weather.html:
<form action="{{ url_for('forecast') }}" method="post">
Enter your address here: <input type="text" name="address"><br>
<input type="submit" name="submit" value="Get My Forecast!"><br>
</form>
When I try to go to 127.0.0.1:5000 I receive this error: "werkzeug.routing.BuildError: Could not build url for endpoint 'forecast'. Did you mean 'home' instead?" To the best of my knowledge this error occurs when url_for fails to find a route, but given that the forecast function does exist I'm confused where the error is coming from. Even after commenting out the form tag in the HTML the error persists. I tried getting rid of the "wfo" and "varying_forecast" in the return statement but that also didn't do anything. The only way to fix it is by setting the url_for of the action of the form to home, but I don't see any way to run the code in there and return the forecast information, considering it's already returning the home page. I'm having trouble understanding why it fails to display the weather.html page as written.

Obtain CSRF-Token and assign to variable

I want to obtain csrf-token provided by flask-wtf and assign it to a variable for future use with my flask app architecture. There's a way to either render it with hidden field {{ form.csrf_token }} or via csrf_token() for jinja. But docs do not mention how to achieve, say, the following:
from flask import Flask, jsonify
from flask_wtf.csrf import CSRFProtect
app = Flask(__name__)
app.secret_key = 'secret'
csrf = CSRFProtect(app)
#app.route('/api/get/endpoint_which_returns_json/', methods=['GET'])
def api():
csrf_token = # ??? what belongs here ???
return jsonify({'token': csrf_token})
if __name__ == '__main__':
app.run(debug=True)
How to achieve that? Thank you in advance.
When you use {{ form.csrf_token }} or {{ csrf_token() }} in your templates through Flask-WTF, they are just calling the flask_wtf.csrf.generate_csrf() function. You can import that and call it yourself to generate a token inside your view:
from flask_wtf.csrf import generate_csrf
#app.route('/', methods=['GET'])
def api():
return jsonify({'token': generate_csrf()})
I'm assuming the idea here is that the api client would be responsible for returning the token with POST requests to your other api resources? If you are just generating the token server-side so as to be able to validate forms that would otherwise require it, you may as well just disable CSRF protection.

In Flask, how can I redirect to a profile being clicked?

I am very new to Flask. I have a mysql database and a template. Let's say I have 3 images
<div><img src= pathOfImage id="profile1"/></div>
<div><img src= pathOfImage id="profile2"/></div>
<div><img src= pathOfImage id="profile3"/></div>
The id of each image (profile1,profile2,profile3) is the primary key of the some tables in the database. What I want to do is to find the values of the corresponding attributes of that tuple by using the primary key. Then, load that those values to the template from the tuples.
And, I have the following code in Python:
from flask import *
#app.route("/")
def index():
return render_template("index.html")
#app.route('/experts')
def route1():
return render_template("experts.html", data=data)
The snippet of HTML code I gave above is in expert.html. I almost of SQL query that was not listed above, data on the second parameter in render_template in route1() is the SQL tuple, which generate all these images and the ID.
I have tried to put a button next to the images, and give id to the button instead. Then, pass the id to the python script as a variable using Ajax, and get the SQL tuple.
However, this isn't the hard part. The hard part is making the new route and loading the content. I have tried make a new route using "app.route" and pass the data into the second parameter of render_template. But, it didn't redirect to a new profile, and the method was called before I even click on the profile.
previously, I used button to retrieve the id:
<html>
<body>
<button id='1'>Button1</button>
<button id='2'>Button2</button>
<button id='3'>Button3</button>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"</script>
<script>
$(document).ready(function() {
$('button').click(function(event) {
var the_id = event.target.id;
$.ajax({
url: "/get_id",
type: "get",
data: {the_id: the_id},
success: function(response) {
},
error: function(xhr) {
}
});
})});
</script>
and, I used these to generate a new template:
import flask
from flask import *
from flaskext.mysql import MySQL
#app.route("/")
def index():
return render_template("index.html")
#app.route('/experts')
def route1():
return render_template("experts.html", data=data)
#app.route('/get_id')
#app.route('/profile')
def route2():
button_id '"' + flask.request.args.get('the_id') + '"'
//some code here to get the tuples that I need "client_info" and
//"skill_info" variable below
return render_template("profile.html", client_info=client_info,
skill_info=skill_info)
Hope someone would give a fresh start. Thanks in advance!
Instead of passing info by ajax you can pass it through the route url.
experts.html
<div><img src="pathOfImage"></div>
<div><img src="pathOfImage"></div>
<div><img src="pathOfImage"></div>
flask routes
import flask
from flask import *
from flaskext.mysql import MySQL
#app.route("/")
def index():
return render_template("index.html")
#app.route('/experts')
def route1():
return render_template("experts.html", data=data)
#app.route('/profile/<id>')
def route2(id):
# id variable contains user profile id string as per user click
# depending on id set variables client_info and skill_info and render
return render_template("profile.html", client_info=client_info, skill_info=skill_info)
{% for profile in profiles %}
<img src="{{profile.img}}">
{% endfor %}
...I guess? maybe?

Categories

Resources