First, the environment
flask==0.10.1
werkzeug==0.10.4
jinja2==2.8
Second, the question
1. Blueprint Architecture
--app
|-user
|-static
|-templates
|-index.html
|-views.py
|-__init_.py
|-box
|-static
|-templates
|-index.html
|-views.py
|-__init_.py
|-__init__.py
2. Recurrence of the problem
user and box are two blueprints, all registered in the app project
If this "render_template (' index.html ')" Renders index.html in the user's views, it may be possible to access template files of the same name under another blueprint.
Third, analysis
1. When the app is created, it reads the template_folder from the Flask registration function, and if not set, the default is App/templates, as the global Jinja_loader
2, the Render_template function will first access the app's global Jinja_loader, which reads the template path.
3. Access to the Jinja_loader of all registered blueprints will be cycled. Since iterating through the unordered dictionary of key values for all blueprints, it happens that one of the blueprints has a template file with the same name and renders the template file.
4, attach key code ( /usr/lib/python2.6/site-packages /flask/templating.py)
def get_source (self, environment, template): for loader, local_name in self._iter_loaders (template): try: return loader.get_source (environment, Local_name) except templatenotfound: pass raise templatenotfound (template) def _iter_loaders (self, template): loader = self.app.jinja_loader if loader is not none: yield loader, template # old style module based loaders in case we are dealing with a # blueprint that is an old style module try: module, local_name = posixpath.normpath (template). Split ('/', 1) blueprint = self.app.blueprints[module] if blueprint_is_module (Blueprint): loader = blueprint.jinja_loader if loader is not none: yield loader, local_name except (ValueError, keyerror): pass for blueprint in itervalues (self.app.blueprints): if blueprint_is_module (Blueprint): continue loader = blueprint.jinja_loader if loader is not none: &Nbsp; yield loader, template
Iv. Solutions
1, the official solution (compromise)
Put all the template files together and draw the molecular catalog by the blueprint name. That is, all of them are placed in the app's global Jinja_loader directory. When visiting, use Render_template (' blueprint_name/template_file.html ') this way. See also: http://flask.pocoo.org/docs/0.10/blueprints/#templates
2, other friends of the solution
Modify the global Jinja_loader when creating the app, and change to choiceloader type , Make each registered Blueprint loader inserted as a dictionary element into the choiceloader prefixloader , This allows you to find the current loader path in Prefixloader based on the name of the passed-in blueprint.
The authors say the benefits do not have to modify the project structure. However, there is a problem: you need to modify the template string when using the render function, because it is prefixloader, you need to add http://fewstreet.com/2015/01/16/flask-blueprint-templates.html
3. Commit on GitHub
This method modifies the Render_template function to determine whether it is a blueprint and whether there is a blueprint loader when rendering the template. If there is a preference for using the blueprint itself loader. This method compares simply directly, see:https://github.com/mitsuhiko/flask/pull/1537/files
4. How to solve my problem
Referring to the idea of the GitHub solution, I changed the global Jinja_loader by Before_request when I registered the app. Temporarily add the Loder path of the current blueprint to the SearchPath list of global Jinja_loader when requested, for the purpose of ① avoid modifying the project structure, ② Avoid modifying the render_template parameters, ③ Avoid modifying the framework code, and it is not convenient to migrate the deployment.
V. My Code (app/__init__.py)
Def create_app (env= ' development '): "" "omit several lines here" "" @app .before_request def before_request (): if request.blueprint is not None: bp = app.blueprints[request.blueprint] if bp.jinja_loader is not none: newsearchpath = bp.jinja_loader.searchpath + app.jinja_loader.searchpath app.jinja_loader.searchpath = newsearchpath
This article is from the "important" blog, please keep this source http://xuke1668.blog.51cto.com/2129485/1712081
Flask Multi-Blueprint Template directory conflict resolution