render_template из чертежа Flask использует шаблон другого чертежа

#python #flask #jinja2

#python #flask

Вопрос:

У меня есть приложение Flask с чертежами. Каждый blueprint предоставляет несколько шаблонов. Когда я пытаюсь отобразить index.html шаблон из второго чертежа, вместо него отображается шаблон первого чертежа. Почему blueprint2 переопределяет шаблоны blueprint1? Как я могу отобразить шаблоны каждого чертежа?

 app/
    __init__.py
    blueprint1/
        __init__.py
        views.py
        templates/
            index.html
    blueprint2/
        __init__.py
        views.py
        templates/
            index.html
 

blueprint2/__init__.py :

 from flask import Blueprint

bp1 = Blueprint('bp1', __name__, template_folder='templates', url_prefix='/bp1')

from . import views
 

blueprint2/views.py :

 from flask import render_template
from . import bp1

@bp1.route('/')
def index():
    return render_template('index.html')
 

app/__init__.py :

 from flask import Flask
from blueprint1 import bp1
from blueprint2 import bp2

application = Flask(__name__)
application.register_blueprint(bp1)
application.register_blueprint(bp2)
 

Если я изменю порядок регистрации чертежей, то шаблоны blueprint2 переопределят шаблоны blueprint1.

 application.register_blueprint(bp2)
application.register_blueprint(bp1)
 

Комментарии:

1. Вы должны опубликовать свои __init__.py файлы.

2. Спасибо, теперь отправлено.

3. Я думаю, проблема в Blueprint('bp1', ... том, что вы должны зарегистрировать полное имя каталога, как в Blueprint('blueprint1',

4. Это не так, я изменил имя, но ничего нового не произошло. Я обнаружил, что порядок, в котором я зарегистрировал проект, определил, какую страницу отображать. Первый, который я зарегистрировал, переопределит второй шаблон.

5. Вы пытались изменить template_folder='templates' ? может быть, чтобы template_folder='blueprint2/templates' ? или дает ему полный путь?

Ответ №1:

Это работает точно так, как задумано, хотя и не так, как вы ожидаете.

Определение папки шаблона для схемы элементов только добавляет папку в путь поиска шаблона. Это не означает, что вызов render_template из представления чертежа будет проверять только эту папку.

Шаблоны просматриваются сначала на уровне приложения, затем в порядке регистрации чертежей. Это делается для того, чтобы расширение могло предоставлять шаблоны, которые могут быть переопределены приложением.

Решение заключается в использовании отдельных папок в папке template для шаблонов, связанных с конкретными чертежами. Их все еще можно переопределить, но гораздо сложнее сделать это случайно.

 app/
    blueprint1/
        templates/
            blueprint1/
                index.html
    blueprint2/
        templates/
            blueprint2/
                index.html
 

Укажите каждый чертеж в его templates папке.

 bp = Blueprint('bp1', __name__, template_folder='templates')
 

При рендеринге укажите на конкретный шаблон под templates папкой.

 render_template('blueprint1/index.html')
 

Подробнее об этом читайте в выпуске Flask №1361.

Ответ №2:

Я смутно помню, что у меня были проблемы с чем-то подобным на ранней стадии. Вы не опубликовали весь свой код, но у меня есть четыре предложения, основанные на том, что вы написали. Попробуйте первый, протестируйте его, а затем, если он все еще не работает, попробуйте следующие, но независимо протестируйте их, чтобы увидеть, работают ли они:

Во-первых, я не могу видеть ваш views.py файл, поэтому убедитесь, что вы импортируете соответствующий шаблон в свои views.py файлы:

 from . import bp1   # in blueprint1/views.py
from . import bp2   # in blueprint2/views.py
 

Во-вторых, вам может потребоваться исправить относительные операторы импорта __init__.py следующим образом (обратите внимание на период, предшествующий вложенным папкам):

 from .blueprint1 import blueprint1 as bp1
from .blueprint2 import blueprint2 as bp2
 

В-третьих, поскольку вы жестко задаете путь к своим шаблонам в своей render_template функции, попробуйте удалить template_folder='templates' его из определения вашего blueprint.

В-четвертых, похоже, что вы назвали url_prefix для своего blueprint как «/bp1» при его регистрации. Поэтому, если жестко запрограммированная ссылка на вашу файловую систему по-прежнему не работает:

 render_template('blueprint1/index.html')
 

затем также попробуйте это и посмотрите, что произойдет:

 render_template('bp1/index.html')
 

Опять же, я не вижу вашего полного кода, но надеюсь, это поможет.