How to constantly update a variable in flask [duplicate] - python

This question already has answers here:
Are global variables thread-safe in Flask? How do I share data between requests?
(4 answers)
Closed 2 years ago.
I want to constantly update my list stuff by appending more "stuff" in it. However, my list is not updating (preferably every second, but I don't know how to do a while loop inside flask).
Here is my routes.py :
from flask import render_template
from app import app
from win32gui import GetWindowText, GetForegroundWindow
#app.route('/')
#app.route('/index')
def index():
user = {'username': 'Miguel'}
stuff = []
stuff.append(GetWindowText(GetForegroundWindow()))
return render_template('index.html', title='Home', user=user, stuff = stuff)
if __name__ == "__main__":
app.run(debug=True)
Here is my index.html :
<html>
<head>
{% if title %}
<title>{{ title }} - Microblog</title>
{% else %}
<title>Welcome to Microblog!</title>
{% endif %}
</head>
<body>
<h1>Hello, {{ user.username }}!</h1>
<h1>Here: </h1>
{% for item in stuff %}
<p> {{ item }} </p>
{% endfor %}
</body>
</html>
When I flask run, there is only ever one item in the list. How do I let the program know I want to continue adding more items? I would like to achieve this in the index() function.
Thank you for your help!

Every time your index method is called, the local variable stuff gets re-initialised to an empty list and then you append an element to it. That's why every time you refresh the page, you only see this one newly added element in stuff.
Consider making stuff global and then add items to it:
from flask import render_template
from app import app
from win32gui import GetWindowText, GetForegroundWindow
stuff = []
#app.route('/')
#app.route('/index')
def index():
global stuff
user = {'username': 'Miguel'}
stuff.append(GetWindowText(GetForegroundWindow()))
return render_template('index.html', title='Home', user=user, stuff = stuff)
if __name__ == "__main__":
app.run(debug=True)
Or store global variables in a more better way.

Related

flask using variables passed in a form in another function [duplicate]

This question already has answers here:
How to pass a variable between Flask pages?
(2 answers)
Closed 1 year ago.
Trying to get two variables via a html form that will be used in other functions later in the code. For now i just want to print the two variables as a test
index.html is:
<html>
<form action="{{ url_for("user_input")}}" method="post">
<label for="a_site">A Site:</label>
<input type="text" id="a_site" name="a_site" placeholder="a_site">
<label for="z_site">Z Site:</label>
<input type="text" id="z_site" name="z_site" placeholder="z_site">
<button> Submit </button>
</form>
</html>
results.html is:
<html>
<body>
{{ a_site_name }} <br>
{{ z_site_name }}
</body>
</html>
Python code
from flask import Flask,render_template,request
app = Flask(__name__)
#app.route('/', methods =['GET', 'POST'])
def user_input():
a_site_name = request.form.get('a_site')
z_site_name = request.form.get('z_site')
return render_template('index.html')
#app.route('/results')
def results():
return render_template('results.html',
a_site_name=a_site_name,
z_site_name=z_site_name
)
def main():
app.run(host='localhost', port=8080)
if __name__ == "__main__":
main()
When i click "Submit" in the browser i get a 500 error, in the flask console the error is NameError: name 'a_site_name' is not defined which makes sense since the results function doesn't know what those two vars are...
I'd usually do something like
a_site_name, z_site_name = user_input() under my main function but that doesn't seem to work either...
So how can i get this to work? Those two vars will end up being used to do a bunch of other python functions which will be invisible to the user, with the end results being displayed on the browser
I think you mismatched form action attribute and href in submit button. Your form is POST-ed to the action URL but then you go to results URL and there is no form posted there.

How to trigger correctly a random.choice() after button selection in Flask?

i am a beginner python student and I trying to build a website that has a single button where each time you click on it a new window will pop up with a random flash game.
now, my button is working but it always opens the same flash game and only when i refresh the page and click again it loads a new game.
can someone please explain to me what is going wrong and how can i fix this? :)
before that i scraped a article with around 150 links to flash games that are now in a .txt file like this for example:
http://www.tapeonline.com/snowball/
http://www.gamesforwork.com/games/play-4626-Necrathalon-Flash_Game
http://www.adobe.com/macromedia/holiday2004/
http://www.kongregate.com/games/arawkins/dolphin-olympics-2
here is my code:
flask
from flask import Flask, render_template, request, redirect
import random
app = Flask(__name__)
#app.route("/" , methods=['POST','GET'])
def home():
if request.method == 'POST':
return redirect("/")
else:
a = open('gamelinks.txt','r')
b = a.read().split()
a.close()
return render_template('index.html', game=random.choice(b))
if __name__ == '__main__':
app.run(debug=True)
html:
{% extends "base.html" %}
{%block head %}
{% endblock %}
<title>FLASHER</title>
{% block body %}
<form action = '{{ game }}' method='POST' target="_blank">
<input type='submit', name='submit', id='submit', value='Play Game'>
</form>
{% endblock %}
The problem is that it chooses randomly only once.
When you load a page random value is assigned to game variable and it stays that way until you refresh page.
You might want to use JS for refreshing page after submitting form:
https://www.w3schools.com/jsref/event_onclick.asp

How can I pass a value from a drop down list to another page in flask

I want to have a page where an option is selected from a drop down list that is passed to the next page. The error I receive is "UnboundLocalError: local variable 'currentuser' referenced before assignment". I'm not sure how to update the variable globally when an option is selected from the drop down list or how to access the global variable locally in the next page function. I am new to python and flask, any help would be greatly appreciated!
app.py
from flask import Flask, render_template
import sqlite3
app = Flask(__name__)
#app.route('/selectusername')
def selectusername_page():
# connect to database and populate userlist
conn = sqlite3.connect('users.db')
c = conn.cursor()
c.execute("SELECT * FROM users")
userlist = c.fetchall()
conn.close()
return render_template('selectusername.html', userlist=userlist)
#app.route('/showusername')
def showusername_page():
currentuser=currentuser
return render_template('showusername.html', currentuser=currentuser)
if __name__ == '__main__':
app.run(debug=True)
selectusername.html
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<body>
<button onclick="window.location.href = 'showusername';">Continue</button>
<h1>Select User</h1>
<select id="currentuser">
{% for user in userlist %}
<option value="{{user[0]}}">{{user[0]}}</option>
{% endfor %}
</select>
</body>
</html>
showusername.html
<h1>Hello {{ currentuser }}</h1>
If you use
<form action="/showusername">
and button without JavaScript and you use name="currentuser" in <select>
<select name="currentuser">
then it can send selected value in url
/showusername?currentuser=selected_name
and you can get it in showusername using request.args
currentuser = request.args.get("currentuser")
To hide name from url you would have to use POST method - so you have to set
<form action="/showusername" method="POST">
and in flask
#app.route('/showusername', methods=['POST', 'GET'])
and then you get it using request.form instead of request.args
currentuser = request.form.get("currentuser")
Full running example
from flask import Flask, render_template, render_template_string, request
app = Flask(__name__)
#app.route('/selectusername')
def selectusername_page():
userlist = [['James'], ['Adam'], ['Mark']]
return render_template_string('''<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<body>
<form action="/showusername">
<button>Continue</button>
<h1>Select User</h1>
<select id="currentuser" name="currentuser">
{% for user in userlist %}
<option value="{{user[0]}}">{{user[0]}}</option>
{% endfor %}
</select>
</form>
</body>
</html>''', userlist=userlist)
#app.route('/showusername', methods=['POST', 'GET'])
def showusername_page():
print('args:', request.args)
print('form:', request.form)
#currentuser = request.args.get("currentuser")
currentuser = request.form.get("currentuser")
return render_template_string('''<h1>Hello {{ currentuser }}</h1>''', currentuser=currentuser)
if __name__ == '__main__':
app.run(debug=True)
If you want to use JavaScript in button then you would have to use JavaScript to get selected value and add it to url like
window.location.href = 'showusername?currentuser=selected_name'
so it is more complicated and I don't put code in JavaScript. Maybe someone else will show this.

Flask 404 page not found

I'm writing a small application in Flask.
run.py
#!flask/bin/python
from app import app
app.run(debug=True, port=9001)
init.py
from flask import Flask
app = Flask(__name__)
from app import views
index.html
{% extends "base.html" %}
{% block content %}
<select id = "foo">
{% for item in Citydata %}
<option value = {{ item.link }}> {{ item.name }} </option>
{% endfor %}
</select>
Click here
{% endblock %}
new.html
{% extends "base.html" %}
{% block content %}
<p>gafgafgadfgaerwgtdfzgaergdfzgaergaergaergt</p>
{% endblock %}
and lastly views.py
from flask import render_template
from app import app
from bs4 import BeautifulSoup
import urllib2
import traceback
class City_Link(object):
name = ""
link = ""
# The class "constructor" - It's actually an initializer
def __init__(self, name, link):
self.name = name
self.link = link
#app.route('/')
#app.route('/index')
def index():
URL = 'http://www.amis.pk/DistrictCities.aspx'
City_Data = scrape(URL)
return render_template("index.html",
title='Home',
Citydata=City_Data)
#app.route('/new/<data>', methods=['GET', 'POST'])
def new(data):
return render_template("new.html",
title='Home',
link = data)
def scrape(url):
data = []
try:
page = urllib2.urlopen(url)
soup = BeautifulSoup(page.read(), "lxml")
table = soup.body.find(id='TABLE1')
for row in table.findAll("tr"):
heads = row.findAll("a")
for head in heads:
data.append((City_Link(head.text.strip(), head.attrs['href'])))
except:
print(traceback.format_exc())
return data
When i click on the "Click me" href in index.html It gives me a 404 not found on the template new.html. I dont understand why because I followed a basic tutorial. I tried changing ports and it worked. But then I tried to update the code and it broke the link again.
So the reason this happens is because flask registers /new and /new/ to be two different routes.
It also looks like you're not actually passing in any data to the data variable anyway. You can temporarily fix this issue by changing your link to point to
/new/something
But that doesn't totally address the problem. I recommend adjusting your template code to make use of flasks excellent url_for function. You can find the extended documentation for it here: http://flask.pocoo.org/docs/0.10/api/#flask.url_for
When we adjust your code, it should look like:
Click here
And that data variable looks like it's not even used! Let's just strip it out totally!
#app.route('/new', methods=['GET', 'POST'])
def new():
return render_template("new.html",
title='Home')
This has altered your code, and I may not have enough information about your use case. If this modifies it beyond being usable for your application, let me know and I'll adjust my answer accordingly.

How to pass items to loop using Jinja2/Flask?

I want to pass a list of pages and loop it in Jinja2 to show all pages of my website. I use Flask to construct and run the app. I followed the official flask documentation, together with this tutorial. However when I try to pass the list and try to loop over it, it does not appear in the rendered html.
What am I doing wrong? How to properly pass the list and loop over it using base.html as a template?
Here is my code with a dummy page list hardcoded:
app.py:
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
page_list = ['Eins', 'Zwei']
return render_template('base.html', pages=page_list)
if __name__ == "__main__":
app.run(port=8000)
And base.html, located in /templates/:
<html>
<head>
<title>Test</title>
</head>
<body>
<h1>All the nice pages</h1>
{% for page in pages %}
<p>{{ page }}</p>
{% endfor %}
</body>
</html>
When I run the app and browse to http://127.0.0.1:8000/, this is what I get:
<html>
<head>
<title>Test</title>
</head>
<h1>All the nice pages</h1>
<body>
</body>
</html>
This code is totally valid. The important thing is to restart the server if you do changes to lists or dictionaries.
Apart from that, in Flask you can pass any type that is built into Python, be it a list, a dictionary or a tuple.
Here are short example for each of the types that pass more or less the same content:
from flask import Flask, render_template
adictionary = {'spam': 1, 'eggs': 2}
alist = ['Eins', 'Zwei', 'Drei']
atuple = ('spam', 'eggs')
app = Flask(__name__)
#app.route('/')
def index():
return render_template('base.html', pages=alist)
#app.route('/tuple/')
def tuple():
return render_template('base.html', pages=atuple)
#app.route('/dict/')
def adict():
return render_template('base.html', pages=adictionary)
if __name__ == "__main__":
app.run(port=8000)
I was having this same issue. I use Sublime Text 3 and realized that I didn't automatically convert tabs to spaces. Once I made that change in the user settings, and reran the script, it output the list correctly.

Categories

Resources