Flask pass a variable from apps main file to a blueprint [duplicate] - python

This question already has answers here:
How to pass arbitrary arguments to a flask blueprint?
(4 answers)
Closed 2 years ago.
How can i pass a variable to a blueprint from the apps main file
Lets say i had the following sample app.
#app.py
from flask import Flask
from example_blueprint import example_blueprint
data_to_pass="Hurray, You passed me"
app = Flask(__name__)
app.register_blueprint(example_blueprint)
#Blueprint
from flask import Blueprint
example_blueprint = Blueprint('example_blueprint', __name__)
#example_blueprint.route('/')
def index():
return "This is an example app"
How do i pass data_to_pass to the blueprint ??
Is there a flask inbuilt way?
I am trying to avoid importing the whole app.py file...it doesnt seem elegant.

If it's a configuration variable, then you could in your app.py add like this app.config['data_to_pass'] and in your blueprint.py you could from flask import current_app and then you can use it like this current_app.config['data_to_pass']. So the code should look like this:
#app.py
from flask import Flask
from example_blueprint import example_blueprint
data_to_pass="Hurray, You passed me"
app = Flask(__name__)
app.config['data_to_pass'] = data_to_pass
app.register_blueprint(example_blueprint)
and then in the blueprint, you can read it like this
#Blueprint
from flask import Blueprint, current_app
example_blueprint = Blueprint('example_blueprint', __name__)
#example_blueprint.route('/')
def index():
data_to_pass = current_app.config['data_to_pass']
return "This is an example app"
This is the best way to use configuration variables I think.

Related

Passing python objects from main flask app to blueprints

I am trying to define a mongodb object inside main flask app. And I want to send that object to one of the blueprints that I created. I may have to create more database objects in main app and import them in different blueprints. I tried to do it this way.
from flask import Flask, render_template
import pymongo
from admin_component.bp1 import bp_1
def init_db1():
try:
mongo = pymongo.MongoClient(
host='mongodb+srv://<username>:<passwrd>#cluster0.bslkwxdx.mongodb.net/?retryWrites=true&w=majority',
serverSelectionTimeoutMS = 1000
)
db1 = mongo.test_db1.test_collection1
mongo.server_info() #this is the line that triggers exception.
return db1
except:
print('Cannot connect to db!!')
app = Flask(__name__)
app.register_blueprint(bp_1, url_prefix='/admin') #only if we see /admin in url we gonna extend things in bp_1
with app.app_context():
db1 = init_db1()
#app.route('/')
def test():
return '<h1>This is a Test</h1>'
if __name__ == '__main__':
app.run(port=10001, debug=True)
And this is the blueprint and I tried to import the init_db1 using current_app.
from flask import Blueprint, render_template, Response, request, current_app
import pymongo
from bson.objectid import ObjectId
import json
bp_1 = Blueprint('bp1', __name__, static_folder='static', template_folder='templates')
print(current_app.config)
db = current_app.config['db1']
But it gives this error without specifying more details into deep.
raise RuntimeError(unbound_message) from None
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.
Can someone point out what am I doing wrong here??
The idea you are attempting is correct; however it just needs to be done a little differently.
First, start by declaring your mongo object in your application factory:
In your app/__init__.py:
import pymongo
from flask import Flask
mongo = pymongo.MongoClient(
host='mongodb+srv://<username>:<passwrd>#cluster0.bslkwxdx.mongodb.net/?retryWrites=true&w=majority',
serverSelectionTimeoutMS = 1000
)
# Mongo is declared outside of function
def create_app(app):
app = Flask(__name__)
return app
And then in your other blueprint, you would call:
from app import mongo # This right here will get you the mongo object
from flask import Blueprint
bp_1 = Blueprint('bp1', __name__, static_folder='static', template_folder='templates')
db = mongo

Extend a blueprint in Flask, splitting it into several files

In flask, I have a blueprint that is getting a bit too long and I'd like to split it into several files, using the same route /games
I tried extending the class, but it doesn't work?
# games.py
from flask import Blueprint
bp = Blueprint('games', __name__, url_prefix='/games')
#bp.route('/')
def index():
...
.
# games_extend.py
from .games import bp
#bp.route('/test')
def test_view():
return "Hi!"
Am I doing something wrong or is there a better way?
You can make it work using absolute path names (packages), here's how:
app.py
from __future__ import absolute_import
from flask import Flask
from werkzeug.utils import import_string
api_blueprints = [
'games',
'games_ext'
]
def create_app():
""" Create flask application. """
app = Flask(__name__)
# Register blueprints
for bp_name in api_blueprints:
print('Registering bp: %s' % bp_name)
bp = import_string('bp.%s:bp' % (bp_name))
app.register_blueprint(bp)
return app
if __name__ == '__main__':
""" Main entrypoint. """
app = create_app()
print('Created app.')
app.run()
bp/init.py
bp/games.py
from __future__ import absolute_import
from flask import Blueprint, jsonify
bp = Blueprint('games', __name__, url_prefix='/games')
#bp.route('/')
def index():
return jsonify({'games': []})
bp/games_ext.py
from .games import bp
#bp.route('/test')
def test_view():
return "Hi!"
Start your server using: python -m app
Then send Get queries to /games/ and /games/test/ endpoints. Worked for me.
Cheers !
In latest version of Flask, it supports Nested Blueprints
They can now be successfully divided into multiple files and imported into the parent one. Additionally, note the url_prefix parameter which can be used to divide files based on functionality but with same routes in different files.

Register global request handler for all blueprints in Flask [duplicate]

This question already has an answer here:
Application-wide request hooks in Flask. How to implement?
(1 answer)
Closed 3 years ago.
I'm trying to register before_request and after_request handlers for all routes (in all blueprints) in Flask.
It's easy to register for a single blueprint:
main = flask.Blueprint('main', __name__)
#main.before_request
def do_something():
flask.request.my_value = 'my_value'
However, I don't know how to accomplish this for all Blueprints. Specifically because I use a factory function to create my app:
def create_app():
from my_package.blueprints.main import main
from my_package.blueprints.user import user
app = Flask(__name__)
app.register_blueprint(main)
app.register_blueprint(user)
return app
Ideally I would like to keep all of my middleware functions in a separate file with something like a root or super Blueprint. Alternatively I suppose I could iterate over all Blueprints on the app object and register these handlers on each, but that seems redundant.
Method 1
You can use before_app_request and after_app_request to register global handler on any blueprint:
#any_bp.before_app_request
def before_all_request:
pass
Method 2
Use before_request and after_request, but register request handler direct for app in application factory:
def create_app():
app = Flask(__name__)
#app.before_request
def before_all_request:
pass
return app

Flask blueprint doesn't work without prefix

Hi I have a Flask app structured in following way and I have problem with blueprints setup. Whatever I do, they only work with url_prefix set up. It works currently as /main/verify but as it is a small app I would love to have an endpoint like /verify. What's interesting I managed to make it work with / route, but for the same configuration it didn't work for the /verify. I am pretty clueless right now, I can live with it as it is, but I really wonder what am I doing wrong.
Here is the code:
__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import config
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
db.init_app(app)
from main import main
app.register_blueprint(main)
return app
main/__init__.py
from flask import Blueprint
main = Blueprint('main', __name__, url_prefix='/main')
from . import views
main/views.py
from flask import request, jsonify
from . import main
#main.route('/')
def index():
return "Hello world"
#main.route('/verify')
def verify():
url = request.args['url']
query = request.args['query']
return jsonify({ ... })
As I see you didn't register blueprint without prefix. If you need to register endpoints without prefix you must create a new instance of Blueprint
main = Blueprint('main', __name__, url_prefix='/main')
# main endpoints(with prefix /main)...
#main.route('/')
def index_main():
return "Hello world from /main/"
# routes without any prefix
default = Blueprint('default', __name__)
#default.route('/')
def index():
return "Hello world from /"
app = Flask(__name__)
app.register_blueprint(main)
app.register_blueprint(default)
Hope this helps.

Flask, Blueprint, current_app

I am trying to add a function in the Jinja environment from a blueprint (a function that I will use into a template).
Main.py
app = Flask(__name__)
app.register_blueprint(heysyni)
MyBluePrint.py
heysyni = Blueprint('heysyni', __name__)
#heysyni.route('/heysyni'):
return render_template('heysyni.html', heysini=res_heysini)
Now in MyBluePrint.py, I would like to add something like :
def role_function():
return 'admin'
app.jinja_env.globals.update(role_function=role_function)
I will then be able to use this function in my template. I cannot figure out how I can access the application since
app = current_app._get_current_object()
returns the error:
working outside of request context
How can I implement such a pattern ?
The message error was actually pretty clear :
working outside of request context
In my blueprint, I was trying to get my application outside the 'request' function :
heysyni = Blueprint('heysyni', __name__)
app = current_app._get_current_object()
print(app)
#heysyni.route('/heysyni/')
def aheysyni():
return 'hello'
I simply had to move the current_app statement into the function. Finally it works that way :
Main.py
from flask import Flask
from Ablueprint import heysyni
app = Flask(__name__)
app.register_blueprint(heysyni)
#app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run(debug=True)
Ablueprint.py
from flask import Blueprint, current_app
heysyni = Blueprint('heysyni', __name__)
#heysyni.route('/heysyni/')
def aheysyni():
# Got my app here
app = current_app._get_current_object()
return 'hello'

Categories

Resources