如何动态选择要在烧瓶中使用的模板目录?

时间:2022-11-23 08:40:29

By default flask uses template files stored in "template" directory :

默认情况下,flask使用存储在“template”目录中的模板文件:

/flaskapp
    /application.py
    /templates
        /hello.html

Is there any way to dynamically choose template directory according to user logged in? This is how I want the directory structure to be :

有没有办法根据用户登录动态选择模板目录?这就是我想要的目录结构:

/flaskapp
    /application.py
    /templates (default template goes here)
        /hello.html
    /userdata
        /user1
            /template1
                 hello.html
            /template2
                 hello.html
        /user2
            /template1
                 hello.html
            /template2
                 hello.html

Now if I have the username of logged in user and the name of template activated by user, is it possible to dynamically select the directory to load template files? For example,

现在,如果我有登录用户的用户名和用户激活的模板名称,是否可以动态选择加载模板文件的目录?例如,

/userdata/<username>/<activated template name>/

instead of fixed

而不是固定的

/templates/

What I am trying to achieve is a wordpress like theme system for my web application where users can upload/select themes for his website.

我想要实现的是像我的网络应用程序的主题系统的wordpress,用户可以上传/选择他的网站的主题。

3 个解决方案

#1


34  

There is also the possibility to overwrite Jinja loader and set the paths where Jinja will look for the templates. Like:

还有可能覆盖Jinja加载器并设置Jinja寻找模板的路径。喜欢:

my_loader = jinja2.ChoiceLoader([
        app.jinja_loader,
        jinja2.FileSystemLoader(['/flaskapp/userdata', 
                                 '/flaskapp/templates']),
    ])
app.jinja_loader = my_loader

Directories are arranged in the order where Jinja needs to first start looking for it. Then from the view you can render user specific template like this:

目录按照Jinja需要首先开始寻找的顺序排列。然后从视图中,您可以渲染用户特定的模板,如下所示:

render_template('%s/template1/hello.html' % username)

where username you can dinamically change in the view. Of course you can also there choose which template (1 or 2) to render. But basically what you really miss is this custom Jinja loader with the custom paths.

用户名,您可以在视图中进行动态更改。当然,您也可以选择要渲染的模板(1或2)。但基本上你真正想念的是这个定制的Jinja加载器和自定义路径。

Hope that helped or gave the ideas :)

希望有所帮助或给出了想法:)

#2


66  

You can pass the Flask constructor a "template_folder" argument.

您可以向Flask构造函数传递“template_folder”参数。

Like so...

像这样......

Flask(__name__, template_folder="wherever")

Here's the documentation: http://flask.pocoo.org/docs/api/

这是文档:http://flask.pocoo.org/docs/api/

#3


2  

I'm new to Python, but I have already faced with this problem. I don't know if my solution is right, but it works:

我是Python的新手,但我已经遇到过这个问题。我不知道我的解决方案是否正确,但它有效:

First of all you have to create module for each user

首先,您必须为每个用户创建模块

/flaskapp
    /application.py
    /templates (default template goes here)
        __init__.py     # default module flaskapp
        views.py        # here you can define methods for default module (like Action in MVC)
        /hello.html
    /static
    /userdata
        /user1
            __init__.py # user1 module
            views.py    # here you can define methods for user1 module
            /template1
                 hello.html
            /template2
                 hello.html
        /user2
            __init__.py # user2 module
            views.py    # here you can define methods for user2 module
            /template1
                 hello.html
            /template2
                 hello.html              

in application.py init Flask app, add global method render_page_from and register blueprints

在application.py init Flask app中,添加全局方法render_page_from并注册蓝图

app = Flask(__name__)
def render_page_from(controller_name, template_name_or_list, **context):
    # here you can choose any controller or use default
    app.jinja_loader.searchpath.clear()
    blueprint = app.blueprints[controller_name]
    app.jinja_loader.searchpath.append(blueprint.template_folder)
    return render_template(template_name_or_list, context=context)

from flaskapp.user1 import controller as user1_controller
from flaskapp.user2 import controller as user2_controller

app.register_blueprint(user1_controller)
app.register_blueprint(user2_controller)

in each module (user1, user2 etc) init blueprint in init.py

在init.py中的每个模块(user1,user2等)初始化蓝图

templates_folder = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')

controller = Blueprint('user1', __name__, url_prefix='/user1', template_folder = templates_folder)

import flaskapp.user1.views

finally add view (action) methods to views.py like this

最后将views(action)方法添加到views.py中

from LocalHub.client import controller
@controller.route('/hello')
def hello():
    """Renders the page"""
    return render_page_from(controller.name, 'hello.html', title='hello')

#1


34  

There is also the possibility to overwrite Jinja loader and set the paths where Jinja will look for the templates. Like:

还有可能覆盖Jinja加载器并设置Jinja寻找模板的路径。喜欢:

my_loader = jinja2.ChoiceLoader([
        app.jinja_loader,
        jinja2.FileSystemLoader(['/flaskapp/userdata', 
                                 '/flaskapp/templates']),
    ])
app.jinja_loader = my_loader

Directories are arranged in the order where Jinja needs to first start looking for it. Then from the view you can render user specific template like this:

目录按照Jinja需要首先开始寻找的顺序排列。然后从视图中,您可以渲染用户特定的模板,如下所示:

render_template('%s/template1/hello.html' % username)

where username you can dinamically change in the view. Of course you can also there choose which template (1 or 2) to render. But basically what you really miss is this custom Jinja loader with the custom paths.

用户名,您可以在视图中进行动态更改。当然,您也可以选择要渲染的模板(1或2)。但基本上你真正想念的是这个定制的Jinja加载器和自定义路径。

Hope that helped or gave the ideas :)

希望有所帮助或给出了想法:)

#2


66  

You can pass the Flask constructor a "template_folder" argument.

您可以向Flask构造函数传递“template_folder”参数。

Like so...

像这样......

Flask(__name__, template_folder="wherever")

Here's the documentation: http://flask.pocoo.org/docs/api/

这是文档:http://flask.pocoo.org/docs/api/

#3


2  

I'm new to Python, but I have already faced with this problem. I don't know if my solution is right, but it works:

我是Python的新手,但我已经遇到过这个问题。我不知道我的解决方案是否正确,但它有效:

First of all you have to create module for each user

首先,您必须为每个用户创建模块

/flaskapp
    /application.py
    /templates (default template goes here)
        __init__.py     # default module flaskapp
        views.py        # here you can define methods for default module (like Action in MVC)
        /hello.html
    /static
    /userdata
        /user1
            __init__.py # user1 module
            views.py    # here you can define methods for user1 module
            /template1
                 hello.html
            /template2
                 hello.html
        /user2
            __init__.py # user2 module
            views.py    # here you can define methods for user2 module
            /template1
                 hello.html
            /template2
                 hello.html              

in application.py init Flask app, add global method render_page_from and register blueprints

在application.py init Flask app中,添加全局方法render_page_from并注册蓝图

app = Flask(__name__)
def render_page_from(controller_name, template_name_or_list, **context):
    # here you can choose any controller or use default
    app.jinja_loader.searchpath.clear()
    blueprint = app.blueprints[controller_name]
    app.jinja_loader.searchpath.append(blueprint.template_folder)
    return render_template(template_name_or_list, context=context)

from flaskapp.user1 import controller as user1_controller
from flaskapp.user2 import controller as user2_controller

app.register_blueprint(user1_controller)
app.register_blueprint(user2_controller)

in each module (user1, user2 etc) init blueprint in init.py

在init.py中的每个模块(user1,user2等)初始化蓝图

templates_folder = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')

controller = Blueprint('user1', __name__, url_prefix='/user1', template_folder = templates_folder)

import flaskapp.user1.views

finally add view (action) methods to views.py like this

最后将views(action)方法添加到views.py中

from LocalHub.client import controller
@controller.route('/hello')
def hello():
    """Renders the page"""
    return render_page_from(controller.name, 'hello.html', title='hello')