Flask Multi-Blueprint Template directory conflict resolution

Source: Internet
Author: User

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.