flacon plan modèle de dossier
Ma gourde application de mise en page est:
myapp/
run.py
admin/
__init__.py
views.py
pages/
index.html
main/
__init__.py
views.py
pages/
index.html
_init_.py fichiers sont vides. admin/views.py contenu est:
from flask import Blueprint, render_template
admin = Blueprint('admin', __name__, template_folder='pages')
@admin.route('/')
def index():
return render_template('index.html')
main/views.py est similaire à admin/views.py:
from flask import Blueprint, render_template
main = Blueprint('main', __name__, template_folder='pages')
@main.route('/')
def index():
return render_template('index.html')
run.py est:
from flask import Flask
from admin.views import admin
from main.views import main
app = Flask(__name__)
app.register_blueprint(admin, url_prefix='/admin')
app.register_blueprint(main, url_prefix='/main')
print app.url_map
app.run()
Maintenant, si j'ai accès http://127.0.0.1:5000/admin/
, il affiche correctement admin/index.html.
Cependant, http://127.0.0.1:5000/main/
montre encore admin/index.html au lieu de main/index.html. J'ai vérifié app.url_map:
<Rule 'admin' (HEAD, OPTIONS, GET) -> admin.index,
<Rule 'main' (HEAD, OPTIONS, GET) -> main.index,
Aussi, j'ai vérifié que l'indice de la fonction dans main/views.py est appelé comme prévu.
Si je renomme main/index.html pour quelque chose de différent, alors il fonctionne. Donc, sans
renommage, comment pouvons réaliser que 1http://127.0.0.1:5000/main/1 montre main/index.html?
Vous devez vous connecter pour publier un commentaire.
De Flacon de 0,8, les bleus ajouter les template_folder à l'application searchpath, plutôt que de traiter chacun des répertoires comme des entités distinctes. Cela signifie que si vous avez deux modèles avec le même nom de fichier, le premier trouvé dans le searchpath est celui utilisé. Ce n'est certes déroutant, et il est mal documenté en ce moment (voir ce bug). Il semble que vous n'étiez pas le seul qui a été confondu par ce comportement.
La conception de la raison de ce comportement est donc que le modèle modèles peuvent être facilement remplacé à partir de l'application principale de modèles, qui sont en première ligne dans la Fiole du modèle searchpath.
Deux options viennent à l'esprit.
index.html
fichiers uniques (par exemple,admin.html
et
main.html
).les modèles dans un sous-répertoire du plan, de dossier, puis appeler
le modèle à l'aide de ce sous-répertoire. Votre modèle d'administrateur, par exemple, serait
yourapp/admin/pages/admin/index.html
, et a ensuite appelé à partir de l'intérieurle plan d'action au
render_template('admin/index.html')
.myapp/templates/admin/index.html
template_folder
à"admin/pages"
ou"main/pages"
?flask1.0
et toujours avoir un problème avec le modèle des répertoires à l'intérieur des plansEn plus de linqq de bonnes suggestions ci-dessus, vous pouvez également remplacer la fonctionnalité par défaut si nécessaire. Il y a deux façons:
On peut remplacer
create_global_jinja_loader
dans un sous-classé Flacon d'application (qui renvoie unDispatchingJinjaLoader
définis dans flask/templating.py). Ce n'est pas recommandé, mais pourrait fonctionner. La raison que c'est déconseillé, c'est que leDispatchingJinjaLoader
a suffisamment de flexibilité pour soutenir l'injection de la coutume des chargeurs. Et si vous vissez votre propre chargeur en place, il va pouvoir se pencher sur par défaut, sane fonctionnalité.Donc, ce qui est recommandé, c'est que l'on "remplacer la
jinja_loader
fonction" à la place. C'est là que le manque de documentation est en. Correctifs Flacon de chargement de la stratégie nécessite quelques connaissances qui ne semble pas être documentées, ainsi qu'une bonne compréhension de Jinja2.Il y a deux composants dont vous avez besoin pour comprendre:
Elles sont créées par Flacon, avec des paramètres par défaut, automatiquement. (Vous pouvez spécifier votre propre Jinja2 options, par la manière, par des raisons impérieuses
app.jinja_options
-- mais gardez à l'esprit que vous perdrez à deux extensions qui Fiole inclut par défaut --autoescape
etwith
-- sauf si vous spécifiez vous-même. Jetez un oeil à flask/app.py pour voir comment ils font référence à ceux-ci.)L'environnement contient tous ceux contexte processeurs (par exemple, de sorte que vous pouvez faire
var|tojson
dans un modèle), des fonctions d'assistance (url_for
, etc) et des variables (g
,session
,app
). Il contient également une référence à un modèle de chargeur, dans ce cas susmentionnés et de l'auto-instanciéDispatchingJinjaLoader
. Ainsi, lorsque vous appelezrender_template
dans votre application, il trouve ou crée de la Jinja2 de l'environnement, met en place toutes ces bonnes choses, et des appelsget_template
sur elle, qui à son tour appelleget_source
à l'intérieur de laDispatchingJinjaLoader
, qui tente quelques stratégies décrites plus tard.Si tout se passe selon le plan, que la chaîne se résoudre à trouver un fichier et retourne son contenu (et certains d'autres données). Aussi, notez que c'est le même chemin d'exécution qui
{% extend 'foo.htm' %}
prend.DispatchingJinjaLoader
fait deux choses: d'Abord, il vérifie si l'application globale de chargeur, qui estapp.jinja_loader
pouvez localiser le fichier. À défaut, il vérifie tous des modèles d'application (par ordre d'inscription, autant que je sache) pourblueprint.jinja_loader
dans une tentative pour localiser le fichier. Suivi de la chaîne à la fin, ici est la définition de jinja_loader (en flask/helpers.py,_PackageBoundObject
la classe de base, à la fois de la Fiole d'application et les Plans):Ah! Alors maintenant que nous voyons. Évidemment, les espaces de noms de conflit au cours de la même noms de répertoire. Depuis le mondial chargeur est appelé en premier, il va toujours gagner. (
FileSystemLoader
est l'un de plusieurs la norme Jinja2 chargeurs.) Cependant, ce que cela signifie, c'est qu'il n'y a pas vraiment de moyen simple de réorganiser le Plan directeur et l'ensemble de l'application du modèle de chargeur.Donc, nous avons besoin de modifier le comportement de
DispatchingJinjaLoader
. Pendant un moment, je pensais qu'il n'était pas bon non découragés et efficace façon d'aller à ce sujet. Cependant, apparemment, si vous remplacezapp.jinja_options['loader']
lui-même, nous pouvons obtenir le comportement que nous voulons. Donc, si nous sous -DispatchingJinjaLoader
, et de modifier une petite fonction (je suppose qu'il pourrait être préférable de le ré-écrire entièrement, mais cela fonctionne pour l'instant), nous avons le comportement que nous voulons. Au total, une stratégie raisonnable serait la suivante (non testé, mais devrait fonctionner avec moderne Flacon applications):Cela modifie la stratégie de l'original chargeur de deux façons: Tentative de chargement du modèle (et SEULEMENT en cours d'exécution plan, pas tous les modèles) en premier, et si cela échoue, alors seulement la charge de l'application. Si vous aimez les tout-plan du comportement, vous pouvez faire quelques copier-pâtes de flask/templating.py.
De lier tout cela ensemble, vous devez définir
jinja_options
sur le Flacon de l'objet:La première fois un modèle de l'environnement est nécessaire (et donc instancié), c'est la première fois render_template est appelée, votre chargeur doit être utilisé.
twooster réponse est intéressante, mais un autre problème est que Jinja par défaut caches un modèle basé sur son nom. Parce que les deux modèles sont nommées "index.html", le chargeur ne fonctionne pas pour la suite des plans.
Outre linqq deux suggestions, une troisième option est de les ignorer le plan de templates_folder option tous ensemble et placer les modèles dans les dossiers respectifs dans l'application du répertoire des modèles.
ie:
index.html
mais alors recommander une alternative qui a encore deux modèles nomméindex.html
. Ai-je raté quelque chose?Je suis en utilisant quelque chose comme ça sur fypress et fybb parce que j'ai un système de thème.
Et puis
Tks @linqq, votre méthode fonctionne vraiment bien ici, d'ailleurs j'ai fait une meilleure solution par le décorateur.
Attention, ici, de ne pas importer le render_template fonction comme ceci:
Vous devez importer le flacon module comme ceci:
Ensuite, faire ce bloc de code en haut de votre routeur fichier:
Remplacer le %YOUR_DIRECTORY_NAME% avec votre chemin, et vous assurer que votre dossier de modèles est comme ceci:
Structure De Dossier
Et tout est fait! Utilisez simplement le render_template fonctionner comme d'habitude.