Using variables across Flask routes [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 4 years ago.
I am learning Flask and have a question regarding use of variables in the context of routes.For Example, my app.py:
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/index")
def index():
a=3
b=4
c=a+b
return render_template('index.html',c=c)
#app.route("/dif")
def dif():
d=c+a
return render_template('dif.html',d=d)
if __name__ == "__main__":
app.run()
Under the route /dif the variable d is calculated by taking the values of already calculated c and a.How to share variables c and a between pages, so that variable d is calculated and rendered to dif.html?
Thank You

If you do not want to use Sessions one way to store data across routes is (See the update below):
from flask import Flask, render_template
app = Flask(__name__)
class DataStore():
a = None
c = None
data = DataStore()
#app.route("/index")
def index():
a=3
b=4
c=a+b
data.a=a
data.c=c
return render_template("index.html",c=c)
#app.route("/dif")
def dif():
d=data.c+data.a
return render_template("dif.html",d=d)
if __name__ == "__main__":
app.run(debug=True)
N.B.: It requires to visit /index before visiting /dif.
Update
Based on the davidism's comment the above code is not production friendly because it is not thread safe. I have tested the code with processes=10 and got the following error in /dif:
The error shows that value of data.a and data.c remains None when processes=10.
So, it proves that we should not use global variables in web applications.
We may use Sessions or Database instead of global variables.
In this simple scenario we can use sessions to achieve our desired outcome.
Updated code using sessions:
from flask import Flask, render_template, session
app = Flask(__name__)
# secret key is needed for session
app.secret_key = 'dljsaklqk24e21cjn!Ew##dsa5'
#app.route("/index")
def index():
a=3
b=4
c=a+b
session["a"]=a
session["c"]=c
return render_template("home.html",c=c)
#app.route("/dif")
def dif():
d=session.get("a",None)+session.get("c",None)
return render_template("second.html",d=d)
if __name__ == "__main__":
app.run(processes=10,debug=True)
Output:

You can use variables in flask using by writing the variable passed from HTML like this in your URL.
,
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/index")
def index():
a=3
b=4
c=a+b
return render_template('index.html',c=c)
#app.route("<variable1>/dif/<variable2>")
def dif(variable1,variable2):
d=c+a
return render_template('dif.html',d=d)
if __name__ == "__main__":
Your html will be like:
as form:
<form action="/{{ variable1 }}/index/{{ variable2}}" accept-charset="utf-8" class="simform" method="POST"
As href:
<span></span> link</li>

Related

Python Code on my XAMPP Website won´t work

from flask import Flask, render_template, request
import random
import datetime
app = Flask(__name__)
# List to store the submitted URLs
urls = []
#app.route('/')
def index():
return render_template('index.html')
#app.route('/submit', methods=['POST'])
def submit():
url = request.form['url']
# Add the URL to the list and return a success message
urls.append(url)
return "URL submitted successfully!"
#app.route('/stream')
def stream():
# Select a random URL from the last 20 days
now = datetime.datetime.now()
twenty_days_ago = now - datetime.timedelta(days=20)
recent_urls = [url for url in urls if url.submission_time > twenty_days_ago]
current_song_url = random.choice(recent_urls)
return render_template('stream.html', url=current_song_url)
if __name__ == '__main__':
app.run(debug=True)
I want to use this Code for my XAMPP Website (Html/php mostly used) but it only shows the code. So I watched some tutorials with config stuff and all that but then there is an internal server error. What should I do?
I tried to config Apache (httpd.conf) and installed everything (Python, Flask etc.)

Flask API - List all resources added [duplicate]

This question already has answers here:
Get list of all routes defined in the Flask app
(11 answers)
Closed 3 years ago.
I've created a simple API using Flask, my question is how do i make it list all of the resources or endpoints it has been assigned
from flask import Flask, request
from flask_restful import Resource, Api
from sqlalchemy import create_engine
from json import dumps
import os, random
app = Flask(__name__)
api = Api(app)
class cuddle(Resource):
def get(self):
file = random.choice(os.listdir("/path/to/dir/of/images"))
out = "https://example.com/path/" + file
return out
api.add_resource(cuddle, '/api/cuddle')
if __name__ == '__main__':
app.run(host="0.0.0.0", port=33, debug=True)
I'm wanting to be able to go to example.com/api/endpoints and for it to list all of the available endpoints, such as in the snippet cuddle
You can use app.url_map.iter_values()
Following is an example
#app.route('/')
def hi():
return 'Hello World!'
#app.route('/hi')
def hi():
return 'Hi!'
#app.route('/hello')
def hello():
return 'Hello World!'
def routes():
routes = []
for route in app.url_map.iter_rules():
routes.append('%s' % route)
print(routes)
['/hello', '/hi', '/']

Python Mock Testing to mock session

I am learning how to test functions in Python using Mock. I am trying to write a test for a simple function,
#social.route('/friends', methods=['GET', 'POST'])
def friends():
test_val = session.get('uid')
if test_val is None:
return redirect(url_for('social.index'))
else:
return render_template("/home.html")
However, I am stuck at how to try and mock session.get('uid') value. So far, this has been my attempt,
#patch('session', return_value='')
#patch('flask.templating._render', return_value='')
def test_mocked_render(self, mocked, mock_session):
print "mocked", repr(self.app.get('/social/friends').data)
print "was _render called?", mocked.called
This attempt may be completely wrong and this is definitely the wrong way as I am still not able to mock session. However, can someone please guide me in the right way through this? Thanks.
Starting with Flask 0.8 we provide a so called “session transaction” which simulates the appropriate calls to open a session in the context of the test client and to modify it.
Let's give a simple example: app.py
from flask import Flask, session
app = Flask(__name__)
app.secret_key = 'very secret'
#app.route('/friends', methods=['GET', 'POST'])
def friends():
test_val = session.get('uid')
if test_val is None:
return 'uid not in session'
else:
return 'uid in session'
if __name__ == '__main__':
app.run(debug=True)
The test file: test_app.py
import unittest
from app import app
class TestSession(unittest.TestCase):
def test_mocked_session(self):
with app.test_client() as c:
with c.session_transaction() as sess:
sess['uid'] = 'Bar'
# once this is reached the session was stored
rv = c.get('/friends')
assert rv.data == 'uid in session'
if __name__ == '__main__':
unittest.main()
run the tests via python test_app.py.
Documentation: Accessing and Modifying Sessions

Object Oriented Python with Flask Server?

I'm using Flask to expose some data-crunching code as a web service.
I'd like to have some class variables that my Flask functions can access.
Let me walk you through where I'm stuck:
from flask import Flask
app = Flask(__name__)
class MyServer:
def __init__(self):
globalData = json.load(filename)
#app.route('/getSomeData')
def getSomeData():
return random.choice(globalData) #select some random data to return
if __name__ == "__main__":
app.run(host='0.0.0.0')
When I run getSomeData() outside of Flask, it works fine. But, when I run this with Flask, I get 500 internal server error. There's no magic here, and Flask has no idea that it's supposed to initialize a MyServer object. How can I feed an instance of MyServer to the app.run() command?
I could admit defeat and put globalData into a database instead. But, is there an other way?
You can create an instance of MyServer just outside the scope of your endpoints and access its attributes. This worked for me:
class MyServer:
def __init__(self):
self.globalData = "hello"
from flask import Flask
app = Flask(__name__)
my_server = MyServer()
#app.route("/getSomeData")
def getSomeData():
return my_server.globalData
if __name__ == "__main__":
app.run(host="0.0.0.0")
I know this is a late reply, but I came across this question while facing a similar issue. I found flask-classful really good.
You inherit your class from FlaskView and register the Flask app with your MyServer class
http://flask-classful.teracy.org/#
In this case, with flask-classful, your code would look like this:
from flask import Flask
from flask_classful import FlaskView, route
app = Flask(__name__)
class MyServer(FlaskView):
def __init__(self):
globalData = json.load(filename)
#route('/getSomeData')
def getSomeData():
return random.choice(globalData) #select some random data to return
MyServer.register(app, base_route="/")
if __name__ == "__main__":
app.run(host='0.0.0.0')
The least-coupled solution is to apply the routes at runtime (instead of at load time):
def init_app(flask_app, database_interface, filesystem_interface):
server = MyServer(database_interface, filesystem_interface)
flask_app.route('get_data', methods=['GET'])(server.get_data)
This is very testable--just invoke init_app() in your test code with the mocked/faked dependencies (database_interface and filesystem_interface) and a flask app that has been configured for testing (app.config["TESTING"]=True or something like that) and you're all-set to write tests that cover your entire application (including the flask routing).
The only downside is this isn't very "Flasky" (or so I've been told); the Flask idiom is to use #app.route(), which is applied at load time and is necessarily tightly coupled because dependencies are hard-coded into the implementation instead of injected into some constructor or factory method (and thus complicated to test).
The following code is a simple solution for OOP with Flask:
from flask import Flask, request
class Server:
def __init__(self, name):
self.app = Flask(name)
#self.app.route('/')
def __index():
return self.index()
#self.app.route('/hello')
def __hello():
return self.hello()
#self.app.route('/user_agent')
def __user_agent():
return self.user_agent()
#self.app.route('/factorial/<n>', methods=['GET'])
def __factorial(n):
return self.factorial(n)
def index(self):
return 'Index Page'
def hello(self):
return 'Hello, World'
def user_agent(self):
return request.headers.get('User-Agent')
def factorial(self, n):
n = int(n)
fact = 1
for num in range(2, n + 1):
fact = fact * num
return str(fact)
def run(self, host, port):
self.app.run(host=host, port=port)
def main():
server = Server(__name__)
server.run(host='0.0.0.0', port=5000)
if __name__ == '__main__':
main()
To test the code, browse the following urls:
http://localhost:5000/
http://localhost:5000/hello
http://localhost:5000/user_agent
http://localhost:5000/factorial/10
a bit late but heres a quick implementation that i use to register routes at init time
from flask import Flask,request,render_template
from functools import partial
registered_routes = {}
def register_route(route=None):
#simple decorator for class based views
def inner(fn):
registered_routes[route] = fn
return fn
return inner
class MyServer(Flask):
def __init__(self,*args,**kwargs):
if not args:
kwargs.setdefault('import_name',__name__)
Flask.__init__(self,*args ,**kwargs)
# register the routes from the decorator
for route,fn in registered_routes.items():
partial_fn = partial(fn,self)
partial_fn.__name__ = fn.__name__
self.route(route)(partial_fn)
#register_route("/")
def index(self):
return render_template("my_template.html")
if __name__ == "__main__":
MyServer(template_folder=os.path.dirname(__file__)).run(debug=True)
if you wish to approach MyServer class as a resource
I believe that flask_restful can help you:
from flask import Flask
from flask_restful import Resource, Api
import json
import numpy as np
app = Flask(__name__)
api = Api(app)
class MyServer(Resource):
def __init__(self):
self.globalData = json.load(filename)
def get(self):
return np.random.choice(self.globalData)
api.add_resource(MyServer, '/')
if __name__ == '__main__':
app.run()

Working with a global singleton in Flask (WSGI), do I have to worry about race conditions? [duplicate]

This question already has answers here:
Are global variables thread-safe in Flask? How do I share data between requests?
(4 answers)
Closed 13 days ago.
The hello world demo for Flask is:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
What if I modified this like so:
from flask import Flask
app = Flask(__name__)
a = 1
b = 2
c = 3
#app.route("/")
def hello():
a += 1
b += a
c += b
return "Hello World!"
if __name__ == "__main__":
app.run()
I understand WSGI application might have multiple threads. The hello function could be running on multiple threads at the same time, and then we'd have a race condition. Is this correct? If the above code is not thread safe, what can I do to make it thread safe?
Avoiding globals is a possible solution, but can you always avoid globals? What if I want something like a python object cache?
You could try the Local class from werkzeug.
Here's some info about it: Context Locals
Example:
from flask import Flask
from werkzeug.local import Local
app = Flask(__name__)
loc = Local()
loc.a = 1
loc.b = 2
loc.c = 3
#app.route("/")
def hello():
loc.a += 1
loc.b += loc.a
loc.c += loc.b
return "Hello World!"
if __name__ == "__main__":
app.run()
You might take a look at the g object that you can import directly from flask, keeps an object globally for that request. If you're using an event driven WSGI server (tornado, gevent, etc) you shouldn't have any issues.

Categories

Resources