web-dev-qa-db-fra.com

Comment sélectionner dynamiquement le répertoire de modèles à utiliser dans le flacon?

Par défaut flask utilise des fichiers de modèle stockés dans le répertoire "modèle":

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

Existe-t-il un moyen de choisir dynamiquement le répertoire de modèles en fonction de l'utilisateur connecté? Voici comment je veux que la structure du répertoire soit:

/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

Maintenant, si j'ai le nom d'utilisateur de l'utilisateur connecté et le nom du modèle activé par l'utilisateur, est-il possible de sélectionner dynamiquement le répertoire pour charger les fichiers de modèle? Par exemple,

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

au lieu de fixe

/templates/

Ce que j'essaie de réaliser est un wordpress comme un système de thème pour mon application Web où les utilisateurs peuvent télécharger/sélectionner des thèmes pour son site Web.

48
anujkk

Il y a également la possibilité de remplacer le chargeur Jinja et de définir les chemins où Jinja recherchera les modèles. Comme:

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

Les répertoires sont classés dans l'ordre où Jinja doit d'abord commencer à le rechercher. Ensuite, à partir de la vue, vous pouvez rendre un modèle spécifique à l'utilisateur comme ceci:

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

où nom d'utilisateur, vous pouvez changer de façon dynamique dans la vue. Bien sûr, vous pouvez également choisir le modèle (1 ou 2) à rendre. Mais ce qui vous manque vraiment, c'est ce chargeur Jinja personnalisé avec les chemins personnalisés.

J'espère que cela a aidé ou donné les idées :)

40
Ignas Butėnas

Vous pouvez passer le constructeur Flask un argument "template_folder".

Ainsi...

Flask(__name__, template_folder="wherever")

Voici la documentation: http://flask.pocoo.org/docs/api/

92
nathan

Je suis nouveau sur Python, mais j'ai déjà rencontré ce problème. Je ne sais pas si ma solution est bonne, mais ça marche:

Tout d'abord, vous devez créer un module pour chaque utilisateur

/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              

dans application.py init Flask app, ajoutez la méthode globale render_page_from et enregistrez les plans

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)

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

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

ajoutez enfin des méthodes de vue (action) à views.py comme ceci

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