I'm not sure if Flask implements all of the routing stuff that Werkzeug does (Flask is based on Werkzeug), but in werkzeug you can use an any route, like so:
gallery = Blueprint(__name__, __name__, url_prefix='/<any("photos,paintings"):source>')
If you use @gallery.route on your views, you'll get an argument source, which you can use to determine your source directory.
@gallery.route('/show')
def show(source):
# Show stuff based on source being "photos" or "paintings"
Not sure if that works in Flask, but worth a shot...
Answer from Menno on Stack OverflowI'm not sure if Flask implements all of the routing stuff that Werkzeug does (Flask is based on Werkzeug), but in werkzeug you can use an any route, like so:
gallery = Blueprint(__name__, __name__, url_prefix='/<any("photos,paintings"):source>')
If you use @gallery.route on your views, you'll get an argument source, which you can use to determine your source directory.
@gallery.route('/show')
def show(source):
# Show stuff based on source being "photos" or "paintings"
Not sure if that works in Flask, but worth a shot...
There are several attributes of request object can be used to get url_prefix of a Blueprint object.
Perhaps request.script_root is simply what you want. For more information, the Flask documentation about request object is recommended.
python - Flask Blueprint Initialization - Initializing some global variables - Stack Overflow
Flask Blueprint issue : Forums : PythonAnywhere
python - How to pass arbitrary arguments to a flask blueprint? - Stack Overflow
Structuring a small Flask app -- wondering if Blueprints is the right approach, or overkill
so each blueprint needs to tell my base application how it want's to be named and what it's default route is.
When you create a blueprint you already pass its name in the first parameter:
simple_page = Blueprint('simple_page')
You can pass to the constructor the url_prefix value too
simple_page = Blueprint('simple_page', url_prefix='/pages')
I have a main application containing some sub applications implemented as blueprints. The main application should hold a navigation bar referencing to all sub applications (blueprints)
This is an example in one python module, you should split each blueprint in its own module.
from flask import Flask, Blueprint, render_template
# ADMIN
admin = Blueprint('admin', __name__, url_prefix='/admin')
@admin.route('/')
def admin_index():
return 'Admin module'
@admin.route('/settings')
def settings():
return 'Admin Settings'
# USER
user = Blueprint('user', __name__, url_prefix='/user')
@user.route('/')
def user_index():
return 'User module'
@user.route('/profile')
def profile():
return 'User Profile'
app = Flask(__name__)
app.register_blueprint(admin)
app.register_blueprint(user)
@app.route('/')
def index():
return render_template('index.html', blueprints=app.blueprints)
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True, port=7000)
The Jinja2 template. Remember to place this file in the templates folder in you root project, which is where flask search the templates by default.
<ul>
{% for bp_name, bp in blueprints.iteritems() %}
<li><a href="{{ bp.url_prefix }}">{{ bp.name }}</a></li>
{% endfor %}
</ul>
From the flask main application object, in this case app, you can access the list of blueprints registered; app.blueprints, which is a python dictionary with the name of the blueprint that you passed in the constructor. So you pass this object to you template and loops on it to render the name and URL in the menu.
Furthermore, what if I want to enable blueprint authors to pass more data in a standardized way (e.g. in which color to display the link to his piece, or whatever...)
As this is a blueprint specific data, I think a good solution is to extend the Blueprint class and implement a custom method to save extra data in a standardized way and then access then from the main application object.
custom.py
from flask import Blueprint
class MyBlueprint(Blueprint):
bp_data = {}
def set_data(data):
# here you can make extra task like ensuring if
# a minum group of value were provided for instance
bp_data = data
admin.py
from .custom import MyBlueprint
admin = MyBlueprint('admin', __name__, url_prefix='/admin')
admin.set_data({'color': '#a569bd', 'enabled': true})
# all the blueprint's routes
...
app.py
from admin import admin
app = Flask(__name__)
app.register_blueprint(admin)
@app.route('/')
def index():
for a, b in app.blueprints:
print b.bp_data['color']
print b.bp_data['enabled']
...
Of course, my custom Blueprint class needs more work on it, like validating what type of data its being passed or throwing an error if there isn't a required value, like; title, require_auth, etc. From this point, it's you who must define what is the minimum required data that a blueprint must provide to your main application to work properly.
Here I present you a extensible app pattern that I usually use. It is proved that work fine.
Directory structure:
YourApp
|- plugins (will contain all the user's plugins)
|- __init__.py (empty)
|-plugin1
|- __init__.py (empty)
|- loader.py
|- app.py
app.py
from flask import Flask
import os
def plugin_loader(app):
""" Function for discover new potencial plugins.
After checking the validity (it means, check if it implements
'register_as_plugin', load the user defined blueprint"""
plugins = [x for x in os.listdir('./plugins')
if os.path.isdir('./plugins/' + x)]
for plugin in plugins:
# TODO: Add checking for validation
module = __import__('plugins.' + str(plugin) + '.loader', fromlist=['register_as_plugin'])
app = module.register_as_plugin(app)
return app
# Creates the flask app
app = Flask(__name__)
# Load the plugins as blueprints
app = plugin_loader(app)
print(app.url_map)
@app.route('/')
def root():
return "Web root!"
app.run()
plugins/plugin1/loader.py
from flask import Blueprint
plugin1 = Blueprint('plugin1', __name__)
@plugin1.route('/version')
def version():
return "Plugin 1"
def register_as_plugin(app):
app.register_blueprint(plugin1, url_prefix='/plugin1')
return app
So futures plugins should implement the register_as_plugin function, inside the loader.py file, inside their directory in plugins/.
For more information about directories discovery you can read https://docs.python.org/2/library/os.path.html. For more information about the dynamic import of modules you can read https://docs.python.org/2/library/functions.html#import.
Proved with Python 2.7.6, Flask 0.10.1 and Unix platform.
You could create the blueprint dynamically in a constructor function:
def construct_blueprint(database):
myblueprint = Blueprint('myblueprint', __name__)
@myblueprint.route('/route', methods=['GET'])
def route():
database = database
return(myblueprint)
Use Flask config system (app.config) to store all your config data, then from your Blueprint read your Application Context using current_app.
Store in app.config:
app.config[DATABASE_URI] = databaseURI
Read application context:
databaseURI = current_app.config[DATABASE_URI]
Sample code
main.py
from flask import Flask
from blueprint import myblueprint
app = Flask(__name__)
app.register_blueprint(myblueprint)
app.config[DATABASE_URI] = databaseURI
blueprint.py
from flask import current_app
myblueprint= Blueprint('myblueprint', __name__)
@myblueprint.route('/route', methods=['GET'])
def route():
databaseURI = current_app.config[DATABASE_URI]
database = OpenDatabaseConnection(databaseURI)
Hello all,
I'm new to Flask. I'm porting an app from PHP (Symfony) to python/flask, and wonder how to organize it.
The app has about 90 endpoints - some JSON/API, some user UI -- in various categories, such as "book" (add/edit/etc), "term" (ditto), "read" (various methods). In Symfony, each of these categories are handled by a separate controller, e.g. BookController.php.
With Flask, I understand I can create blueprints, but none of these are "subsystems", they're all related to the central idea of the app, and I'm not going to need them to be modular pick-up-and-drop-in pieces.
I'm inclined to make them all blueprints anyway, just because that seems to be easy to grok for any newcomers to the project, if people want to work on it. I'd be interested to know if there were any other good alternatives, such as simple python files (e.g. "routes/book_routes.py").
Thank you very much!