Python, Flask: Importing functions and variables inside blueprint - python

How to import a function and variable from app/__init__.py and app/blueprint/__init__.py , respectively, inside app/blueprint/views.py ?
app/__init__.py
def main():
<..>
app/blueprint/__init__.py
from flask import Blueprint
blueprint = Blueprint('blueprint', __name__, template_folder='templates')
app/blueprint/views.py
import blueprint
import main

from app.__init__ import *
from app.blueprint.__init__ import *
should import all the functions and variables from both files.
However, though I don't think init file is supposed to be used for this.
Below examples of Flask Blueprints I used my project, learnt structure from Udemy tutorial, I think the idea is generally the init files are used to make a Python directory into a package so you can import stuff within it. You'd probable better create new files with the functions (less often variables) you want to import, maybe experts will confirm, but I think generally you leave Python init files blank unless you really know what you're doing.
from flask import Flask, render_template
from Source.common.database import Database
from Source.models.users.views import user_blueprint
from Source.models.street_lists.views import street_list_blueprint
# from Source.models.street_reports.views import street_report_blueprint
__author__ = "Will Croxford, with some base structure elements based on Github: jslvtr, \
from a different tutorial web application for online price scraping"
app = Flask(__name__)
app.config.from_object('Source.config')
app.secret_key = "123"
app.register_blueprint(user_blueprint, url_prefix="/users")
app.register_blueprint(street_list_blueprint, url_prefix="/streetlists")
# app.register_blueprint(street_report_blueprint, url_prefix="/streetreports")
#app.before_first_request
def init_db():
Database.initialize()
#app.route('/')
def home():
return render_template('home.jinja2')
#app.route('/about_popup.jinja2')
def info_popup():
return render_template('about_popup.jinja2')
Flask Views file example:
# In this model, views.py files are the Flask Blueprint for this object.
# ie they describe what HTTP API endpoints are associated to objects of this class.
from flask import Blueprint, render_template, request, redirect, url_for
from Source.models.street_lists.street_list import StreetList
__author__ = 'jslvtr'
street_list_blueprint = Blueprint('street_lists', __name__)
#street_list_blueprint.route('/')
def index():
prop_query = StreetList.get_from_mongo(streetpart="bum")
return render_template('street_lists/street_list.jinja2', stores=prop_query)
You can look at pocoo.org flask doc examples, and search other SO questions for Flask blueprint template examples I think. Good luck!

I read the blog suggested by Will Croxford, and here's the solution to my problem:
app/blueprint/views.py
from app import main
from app.blueprint import blueprint

Related

Converting a flask app to an application factory pattern screws up all imports

So i've been building a flask app just using an app.py file and running it.
It has quite a big app now and i'm now just trying to convert it into an application factory because I need to use SQLAlchemy in my Celery tasks.
here is my init.py in my app folder
def create_app():
load_dotenv(".env")
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///data.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["PROPAGATE_EXCEPTIONS"] = True
app.config["BROKER_URL"] = os.getenv("REDIS_BACKEND_BROKER")
app.config["CELERY_BROKER_URL"] = os.getenv("REDIS_BACKEND_BROKER")
app.config["CELERY_IMPORTS"] = "celery_tasks"
app.secret_key = os.getenv("SECRET_KEY")
CORS(app)
api = Api(app)
jwt = JWTManager(app)
db.init_app(app)
ma.init_app(app)
celery.init_app(app)
#app.before_first_request
def create_tables():
db.create_all()
#jwt.invalid_token_loader
def invalid_token_callback(self):
return {"message": "invalid"}, 401
with app.app_context():
from .resources.auth import Auth, CheckUser
from .resources.period import Period
from .resources.project import Project
from .resources.session import Session
api.add_resource(Auth, "/auth")
api.add_resource(CheckUser, "/check")
api.add_resource(Project, "/createproject")
api.add_resource(Period, "/createperiod")
api.add_resource(Session, "/createsession")
return app
The problem is that all the resources that being imported breaks because they can no longer import based on modules either.
For example resources.period also imports SQLAlchemy models and Masrhmallow schemas
resources/period.py
#THESE ARE NO LONGER IMPORTED SUCCESSFULLY
from models.project import ProjectModel
from schemas.task import TaskSchema
from schemas.period import PeriodSchema
Here is my file structure
This is an awesome tutorial by Miguel Grinberg where he refactores a complete application like you want it, too:
https://www.youtube.com/watch?v=NH-8oLHUyDc&t=2934s
Did you try to make an "absolute" import like:
from app.models.project import ProjectModel
Since you're importing from resources/period.py using relative imports, you need to go up a level:
from ..models.project import ProjectModel
from ..schemas.task import TaskSchema
from ..schemas.period import PeriodSchema

How to put decorators on `app` when using Application Factory with Flask?

I'm trying to define some global constants for my app, and have found that this can be done with a function that's decorated as #app.context_processor.
However, the issue is that I don't have an app variable. My application uses an application factory, and I'd like to keep it that way. Is there a different way to register a function as the context_processor for my app?
One option I have seen is to apply the decorator to each Blueprint instead of applying it to the app. That's something I would like to avoid though, since it would lead to a lot of duplicate code.
The issue is that there is no app object in case of factories. You have a create_app function where the app gets created.
So to install the context processors you can use create_app itself
def create_app(config_filename):
app = Flask(__name__)
app.config.from_pyfile(config_filename)
from yourapplication.model import db
db.init_app(app)
from yourapplication.context_processor import myprocessor
app.context_processor(myprocessor)
from yourapplication.views.frontend import frontend
app.register_blueprint(frontend)
return app
You could also have the function in the same app.py file (wherever the create_app() function is written). In such a case, you could simply register the context_processor without importing it.
Another approach is to do it in a blueprint as shown in below
Flask context processors functions
from flask import Blueprint
thingy = Blueprint("thingy", __name__, template_folder='templates')
#thingy.route("/")
def index():
return render_template("thingy_test.html")
#thingy.context_processor
def utility_processor():
def format_price(amount, currency=u'$'):
return u'{1}{0:.2f}'.format(amount, currency)
return dict(format_price=format_price)

How to access flask config variables outside application context according to my project structure?

spinngod.py - flask app starter code
from app import create_app
import sys
run_profile = str(sys.argv[1]) if len(sys.argv) >= 2 else 'development'
app = create_app(run_profile)
print("App Root Path:" + app.root_path)
if __name__ == '__main__':
print sys.path
app.run(debug=True, host='0.0.0.0')
app/init.py - creates flask app
def create_app(profile_name):
print "currently active profile:" + profile_name
app = Flask(__name__)
############# configurations ####################
app.config.from_object(config[profile_name])
configure_app(app)
configure_app_logger(app)
#################### blueprint registration and rest_plus namespace additions ###############
from api_1_0 import api as api_1_0_blueprint
from api_1_0.restplus import api_restplus
# ************************************************** #
api_restplus.init_app(api_1_0_blueprint)
api_restplus.add_namespace(application_namespace)
api_restplus.add_namespace(pipeline_template_namespace)
api_restplus.add_namespace(loadbalancer_namespace)
api_restplus.add_namespace(servergroup_namespace)
api_restplus.add_namespace(task_namespace)
# ************************************************** #
app.register_blueprint(api_1_0_blueprint)
##############################################################
return app
I want to access flask config variables defined in config.py in some other files which are outside application context. The app configuration depends on which profile it is started with (dev,stage or production) which is being passed from command line as an arg.
The only way that I can think of accessing config variables outside app context is to set profile (dev,stage or prod) as an environment variable and
then import directly from config file.
The second way that I tried was to move creation of flask app in app/init.py outside method.
This is how I am trying to access config variables in another class.
import requests
class Client(object):
def __init__(self):
from app import app
print "fjaijflkajsf" + app.config['SPINNAKER_BASE_URL']
pass
Is there a way better of doing this in flask ?
From the docs:
Rather than passing the application around to each function, the current_app and g proxies are accessed instead.
The Flask application object has attributes, such as config, that are useful to access within views and CLI commands. However, importing the app instance within the modules in your project is prone to circular import issues.
Flask solves this issue with the application context. Rather than referring to an app directly, you use the the current_app proxy, which points to the application handling the current activity.
You import current_app like this:
from flask import current_app
and then access the config or other attributes like this:
config = current_app.config
Example:
src/application.py (where config is set in the context)
create_app():
app = Flask('app')
app.config.from_object(some_class)
return app
src/module/another_module.py
from flask import current_app
def function_that_requires_config():
config = current_app.config
Alternative:
src/application.py (where config is set in the context)
APP = create_app(os.environ.get('FLASK_ENV'))
src/module/another_module.py
from src.application import APP
def function_that_requires_config():
config_value = APP.config.get(config_key, default_value)
Not sure if it is good to put it here as it may not respond to the question directly, but here is the cleanest way i've figured to use config values outside of requests, without having to pass config as a param.
The solution is actually pretty simple, juste consider the part of your code as a flask_extension.
my exemple will be the use of external api, with ROOT_URL in the config file, and i don't want to make api call from within my routes, so the api is in its own module.
in my create_app fuction:
from flask import Flask
from .api import api
from .configmodule import Config
from .model import db
def create_app(environment):
app = Flask(__name__)
app.config.from_object(Config.get_config(environment))
db.init_app(app)
api.init_app(app) # here i use api.init_app the same way i do for sqlalchemy
and in api/init.py
class Api:
def init_app(self, app):
self.config = app.config
api = Api()
and in any files in my api modude i can now write
from . import api
def foo():
print(api.config.get("API_ROOT_URL"))
this can even be improved if you feel the need to access some other global app vars from your module.

How to share the global app object in flask?

I am using flask and trying to the following.
I have defined a main.py file through which I want to run my app ie python main.py -
from flask import Flask
from view import tags
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
I have defined a package named view in which I will be declaring my different view modules, each having its own routes. view.tags.py -
from flask import Flask
app = Flask(__name__)
#app.route('/e')
def hello_world2():
return 'Hello World!'
So I need to have the global app object in my main.py for running the server, as well as in the view classes of my package for registering the routes. So how do I create the global app object and share it between all classes ?
Thanks,
Murtaza
You can import current_app from flask. It stores a reference to the global application object.
from flask import current_app as app
def home():
return render_template('base.html', name=app.name)
First, I would suggest to take a look at Blueprints http://flask.pocoo.org/docs/blueprints/ This will help to organize the app easily.
Also take a look at http://flask.pocoo.org/docs/api/#flask.current_app flask.current_app, the way how to get your app instance in other modules.
This link also could be helpful on how to organize and build flask app (it is not ideal for sure, but can give you some ideas) - Large-app-how-to.md
Have fun :)
One way is to create an overall package and adding a __init__.py file under that where you declare all global variables. In your case for example, you can create something like:
myapplication/
* __init__.py
* myviews/
* __init__.py
* view.py
* tags.py
etc
Now you add the following code in the __init__.py file:
app = Flask(__name__)
You can now use this app variable anywhere as long as you import the package myapplication.
import myapplication.myviews.view
Just import it from your other files. Perhaps the best way to do this is to put your app object in one single file and have everything else import from it.
For example, your main.py could still have:
from flask import Flask
from view import tags
app = Flask(__name__)
And then in other files, you could do:
from .main import app
or, if outside your package, just use the complete string
from mypackagename.main import app
One thing to be careful of is circular imports. The easiest way to handle this issue is to create your app first and then import whatever else you need to from your base file after you create it.
So for example:
from flask import Flask
app = Flask(__name__)
# do some stuff with app
from .views import view1, view2
from .server import run
So long as you put the imports after you've created app, like the above, you shouldn't have an issue with circular imports.
Regarding import and use of current_app from flask in a "helper" python function in a separate source file, this works as long as a current app context has already been set up (E.g. web request received). I have a case where, during application initialization (app.run not yet invoked), app.logger is invoked in the helper function.
Before I fixed it (see below), I got a stack trace punctuated by "RuntimeError: Working outside of application context".
Sample solution:
main.py:
import helper
...
app = Flask(__name__.split('.')[0],
template_folder="templates",
static_folder="static")
...
# Fix: Create an app context
with app.app_context():
helper.dbopen(...)
...
app.run(...)
helper.py:
from flask import current_app as app
...
def dbopen():
app.logger.info(...)
...
If you have a file AppName.py in which you define app, and then you have another file Foobar.py that needs it, you can always say in AppName.py:
import Foobar
Foobar.app = app
Then in Foobar.py you should be able to use app in your functions. One thing you want to be careful of is that you can't have code in Foobar.py that runs immediately when the file is called the depends on the app variable which is passed in after the import.

Is it possible to import flask configuration values in modules without circular import?

I'm using Flask with Blueprints to get a skeleton for my website and I'm having a problem using configuration classes deep in my application.
Here's some dummy code that explains how I've set everything up:
websiteconfig.py
class Config(object):
pass
class ProductionConfig(Config):
DEBUG = False
class DevelopmentConfig(Config):
DEBUG = True
website/__ init __.py:
# Some app code and config loading
app = Flask('website')
app.config.from_object('websiteconfig.DevelopmentConfig')
# Import some random blueprint
from website import users
app.register_blueprint(users.api)
# This works:
# print app.config['DEBUG']
website/users/__ init __.py:
from flask import Blueprint
from website.users.models import test
api = Blueprint('users', __name__, url_prefix='/users')
# This works:
# print api.config['DEBUG']
# From models
print test()
website/users/models.py:
# How can I reach the config variables here?
def test():
# I want config['DEBUG'] here
How can I reach the configuration variables stored in the class I load in app.py deep inside the users package?
Is a circular import like from website import app (inside models.py) an accepted solution?
If not, is there some simple solution I've missed?
I believe you can use flask's current_app idiom for that.
http://flask.pocoo.org/docs/api/#flask.current_app
from flask import current_app
def test():
return current_app.config.get('some_config_value')

Categories