Is there any way of a 'global GET management' in Flask?
For example:
I want to show an error message, via popover, on any page of my flask application. If the user clicks on the 'close' button, the application will make a reload of the page with a new get parameter 'message_read=1'.
I want to catch this GET parameter. I am quite sure there is a better way then writing a check in every single app.route (which are a lot). Could you give me a hint please.
Thank you.
Add a before request function and handle it there. http://flask.pocoo.org/docs/0.12/api/#flask.Flask.before_request
#app.before_request
def do_stuff():
arg = request.args.get('message_read')
You may use decrators . Read about python decorators here
Here is a demonstration of custom decorator with flask.The code below shows a decorator definition and usage for your use case
Code
from flask import Flask,request
from functools import wraps
def popup_message(f):
#wraps(f)
def f_(*args,**argv):
message_read = request.args.get('message_read', None)
if message_read is not None:
return message_read
else:
return f(*args,**argv)
return f_
app = Flask(__name__)
#app.route('/earth')
#popup_message
def hello_earth():
return 'Hello,earth'
#app.route('/world')
#popup_message
def hello_world():
return 'Hello, World!'
app.run()
Usage
Run the app as
python main.py
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
and try making request to /earth and /world with and without message_read
Related
I'm trying to run Flask from an imported module (creating a wrapper using decorators).
Basically I have:
app.py:
import mywrapper
#mywrapper.entrypoint
def test():
print("HEYO!")
mywrapper.py
from flask import Flask
ENTRYPOINT = None
app = Flask(__name__)
#app.route("/")
def listen():
"""Start the model API service"""
ENTRYPOINT()
def entrypoint(f):
global ENTRYPOINT
ENTRYPOINT = f
return f
FLASK_APP=app
Running python -m flask, however, results in:
flask.cli.NoAppException: Failed to find Flask application or factory in module "app". Use "FLASK_APP=app:name to specify one.
Is there any trick to getting Flask to run like this? Or is it just not possible? The purpose of this is to abstract Flask away in this situation.
In my head flask should try to import mywrapper.py, which imports app.py which should generate the app and route, yet this doesn't seem to be what occurs.
Any help would be appreciated.
So I've since learnt that Flask searches only in the chosen module's namespace for a variable containing a Flask object.
There may be a smart way to avoid this limitation, but I instead decided that it was more sensible to instead just wrap the Flask class itself. If people want direct Flask functionality, I don't really care in this situation, so the only real limitation I have from this is some function names are off limits.
Basically:
wrapper.py:
class Wrapper(Flask):
def __init__(self, name):
super().__init__(name)
self.entrypoint_func = None
#self.route("/")
def listen():
return self.entrypoint_func()
def entrypoint(self, f):
assert self.entrypoint_func is None, "Entrypoint can only be set once"
self.entrypoint_func = f
return f
and app.py:
from mywrapper import Wrapper
app = Wrapper(__name__)
#app.entrypoint
def test():
print("HEYO!")
return "SUCCESS"
This is still abstracted enough that I am happy with the results.
In the populair web framework flask a basic web page looks like this:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
I am pretty new to python and i was wondering how this exactly works. I get that # is a decorator that decorates the hello function but how does flask that is has to call the underlying hello funtion or even knows it exists, because the code does not run the hello function like this:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
hello()
When i am coding i like to know how something works before i just randomly accept anything. I searched my but off looking for an answer but could not find a pleasent answer. Also i looked in the source code but i was not able to find out how it works
So now the real question: How can i recreate something similair in plain python? So running a function without really calling it in the main code first.
Ps. Sorry for my bad english, it is not my main language.
app.route() remembers the URL ("/") and the function associated with it (hello). Later, app.run() can query that association and invoke hello.
How can i recreate something similair in plain python?
This program might give you an understanding of how hello() is invoked:
class Flask:
def __init__(self):
self.routes = {}
def route(self, path):
def wrapper(fn):
self.routes[path] = fn
return fn
return wrapper
def run(self):
# Networking code goes here.
# Suppose "/" comes in as a request, then this happens:
self.routes["/"]()
app = Flask()
#app.route("/")
def hello():
print("Inside hello")
return "Hello World!"
app.run()
Alternatively, you can examine the flask source: https://github.com/pallets/flask Specifically, app.route() is defined here: https://github.com/pallets/flask/blob/0.12.2/flask/app.py#L1054 and the call to hello() is here: https://github.com/pallets/flask/blob/0.12.2/flask/app.py#L1052
I have created an app.py and index.html file. My problem is that I want to execute a python script with the input I gathered from POST when submit is clicked, and then display the script output on the same or different html page. I used CGI and Flask. I do not fully know how to proceed. I research online, but couldn't find anything very helpful. Any help would be appreciated.
Here is my code.
from flask import Flask, render_template, request, redirect
app = Flask(__name__)
#app.route("/")
def main():
return render_template('index.html')
#app.route("/src_code/main.py", methods = ['POST'])
def run_app():
id = request.form['id']
name = request.form['name']
url = request.form['url']
if not id or not name or not url:
return render_template('index.html')
else:
#execute the python script.
if __name__ == "__main__":
app.run()
EDIT:
I have used the following code to import my function. At the end, though I have received an error when I clicked the submit button on index.html
script_analyze = Analyzer()
result = script_analyze.main()
return render_template(results.html', data=result)
AttributeError: 'WSGIRequestHandler' object has no attribute 'environ'
I am unsure why this attribute error is raised.
Since you want to execute another Python script... If you are able to import the other script then you can just use something like the following to call it and store the results - assuming the other script is a value-returning function.
from othermodule import function_to_run
...
# where you want to call it
result = function_to_run()
Then you can use render_template as others have said, passing this result as the data to the template (or simply return the result if it's already in the format you want to output with Flask).
Does that work, or is the script you want to run something that this wouldn't work for? Let us know more about the script if it's an issue.
I'm using Python Flask and I got defined the following function:
def verify_session():
if not 'logged_in' in session:
flash("You are not logged in.<br/>Please, log in to use our application.", "warning")
return redirect(url_for('login_path'))
This is meant to be called in every controller. I know that I could use #app.before_request but on some places I dont want this function to be called (in the same Login page, for example) and I really dont want the function to check the excluded paths.
My problem is this: inside any Flask controller for each of the paths the first lines look like this:
#app.route('/web/account', methods=["GET"], endpoint="account_path")
def account():
verify_session()
return render_template('account')
But, despite I get the "You need to login" flashed message, it still returns the Account page, because the return inside verify_session just returns for this function.
What I need is something like return verify_session() but that doesn't end the controller flow unless it actually is necessary to return it.
Maybe this problem is only Python/Programming specific rather than Flask so I excuse myself and ask moderators to edit my Question accordingly. I mention Flask because it's the enviroment where I'm having the trouble.
IF more information is needed I'm willing to update. Thank you in advance.
result = verify_session()
if not result:
result = render_template("account")
return result
but really you should be using a decorator for this
def verify_session(fn):
def inner(*args,**kwargs):
if not 'logged_in' in session:
flash("You are not logged in.<br/>Please, log in to use our application.", "warning")
return redirect(url_for('login_path'))
return fn(*args,**kwargs)
return inner
then you would use it like
#app.route('/web/account', methods=["GET"], endpoint="account_path")
#verify_session #make sure to use any decorators after the route decorator
def account():
return render_template('account')
lastly ... I hope you are aware that you are reinventing the wheel and you should probably just use flask-login to manage this stuff(unless you have a pretty compelling reason not to)
To add to Joran's excellent answer. Instead of using #app.before_request, you can put your login required routes in a blueprint and then use #blueprint.before_request:
account = Blueprint('account', __name__)
#account.before_request
def verify_session():
...
#account.route('/')
def index():
...
Then in your app:
app = Flask(__name__)
app.register_blueprint(account, url_prefix='/web/account')
i am using python 2.6.5 to develop an app for google app engine - i am not too familiar with python, but i'm learning.
i am trying to put a url into a string so variable = "string http://domain.name"
then i print the string out. the problem is, if the colon (after http) is in the string, i don't get any output and i don't know why.
i've tried escaping the string with:
"""http://domain.name"""
r"http://domain.name"
"http\://domain.name"
"http\://domain.name"
"http\\://domain.name"
"http:://domain.name"
none of them seem to work and i'm not sure what else to try
The context is like so
variables.py is:
...
HOST_URL = "http://domain.name"
...
example logout.py
import variables
import sys
...
class Logout(webapp.RequestHandler):
""" RequestHandler for when a user wishes to logout from the system."""
def post(self):
self.get()
def get(self):
print(variables.HOST_URL)
print('hi')
self.redirect(variables.HOST_URL)
sys.exit()
or
in file functions.py
import variables
import sys
...
def sendhome(requesthandler)
print 'go to '+variables.HOST_URL
requesthandler.redirect(variables.HOST_URL)
sys.exit()
called from a context like:
from functions import sendhome
...
class Logout(webapp.RequestHandler):
""" RequestHandler for when a user wishes to logout from the system."""
def post(self):
self.get()
def get(self):
sendhome(self)
any help would be appreciated
thanks
If I'm not terrible mistaken, GAE uses WSGI, you do not simply print things, you are supposed to return a proper HTTP response object (it is not PHP).
I guess that if you access the page using firefox+firebug and look at the network->header you will see that the browser is taking http: as an HTTP header with value "//domain.name".
Edited: By the way, should not you be using "self.response.out.write" instead of "print"?
The problem was the sys.exit() after the call to print or redirect