Flask викликає помилку TemplateNotFound, навіть якщо файл шаблону існує


107

Я намагаюся відтворити файл home.html. Файл існує в моєму проекті, але я продовжую отримувати, jinja2.exceptions.TemplateNotFound: home.htmlколи намагаюся його відтворити. Чому Flask не може знайти мій шаблон?

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('home.html')
/myproject
    app.py
    home.html

Відповіді:


212

Ви повинні створити файли шаблонів у правильному місці; у templatesпідкаталозі поруч із вашим модулем python.

Помилка вказує на відсутність home.htmlфайлу в templates/каталозі. Переконайтеся, що ви створили цей каталог в тому ж каталозі, що і ваш модуль python, і що ви насправді помістили home.htmlфайл у цей підкаталог. Якщо ваша програма є пакетом, папка шаблонів повинна бути створена всередині пакету.

myproject/
    app.py
    templates/
        home.html
myproject/
    mypackage/
        __init__.py
        templates/
            home.html

Крім того, якщо ви назвали папку шаблонів інакше, ніж templatesне хочете перейменовувати її за замовчуванням, ви можете сказати Flask використовувати цей інший каталог.

app = Flask(__name__, template_folder='template')  # still relative to module

Ви можете попросити флягу , щоб пояснити , як він намагався знайти цей шаблон, встановивши EXPLAIN_TEMPLATE_LOADINGопцію в True. Для кожного завантаженого шаблону ви отримаєте звіт, зареєстрований у колбіapp.logger на рівні INFO.

Ось так це виглядає, коли пошук успішний; у цьому прикладі foo/bar.htmlшаблон розширює base.htmlшаблон, тому існує два пошуки:

[2019-06-15 16:03:39,197] INFO in debughelpers: Locating template "foo/bar.html":
    1: trying loader of application "flaskpackagename"
       class: jinja2.loaders.FileSystemLoader
       encoding: 'utf-8'
       followlinks: False
       searchpath:
         - /.../project/flaskpackagename/templates
       -> found ('/.../project/flaskpackagename/templates/foo/bar.html')
[2019-06-15 16:03:39,203] INFO in debughelpers: Locating template "base.html":
    1: trying loader of application "flaskpackagename"
       class: jinja2.loaders.FileSystemLoader
       encoding: 'utf-8'
       followlinks: False
       searchpath:
         - /.../project/flaskpackagename/templates
       -> found ('/.../project/flaskpackagename/templates/base.html')

Креслення можуть також реєструвати власні каталоги шаблонів , але це не є вимогою, якщо ви використовуєте креслення, щоб полегшити розподіл більшого проекту на логічні блоки. У головному каталозі шаблону програми Flask завжди спочатку здійснюється пошук, навіть при використанні додаткових шляхів за проектом.


2
EXPLAIN_TEMPLATE_LOADING дуже корисний для налагодження проблем із шляхами навколо шаблонів. Крім того, якщо ви використовуєте креслення, переконайтеся, що ви встановили template_folderшлях для кожного креслення .
Джастін Краузе

1
@JustinKrause: спасибі за це, EXPLAIN_TEMPLATE_LOADINGбуло додано після того, як ця відповідь була спочатку написана.
Мартін Пітерс

1
Здається, моя локальна колба (у Windows) може знаходити шаблони всередині ./Templates/index.html, але коли я розгортаю heroku (думав, що це той самий Python, ті самі версії бібліотеки, включаючи ту саму версію Flask; але heroku - це Unix); і викидає TemplateNotFoundпомилку; після того, як я перейменував папку git mv Templates/index.html templates/index.html, працювали як локальна (Windows), так і heroku (Unix) версія
The Red Pea

1
@TheRedPea так, оскільки файлова система Windows складається так, що Templates== templates. Але Heroku працює під управлінням Linux із чутливою до регістру файловою системою.
Мартін Пітерс

11

Я думаю, що Flask використовує шаблони каталогів за замовчуванням. Тож ваш код повинен припустити, що це ваш hello.py

from flask import Flask,render_template

app=Flask(__name__,template_folder='template')


@app.route("/")
def home():
    return render_template('home.html')

@app.route("/about/")
def about():
    return render_template('about.html')

if __name__=="__main__":
    app.run(debug=True)

І ви працюєте в структурі простору, як

project/
    hello.py        
    template/
         home.html
         about.html    
    static/
           js/
             main.js
           css/
               main.css

також ви створили два файли HTML з назвою home.html та about.html і помістили ці файли в папку шаблону.


8

(Зверніть увагу, що прийнята вище відповідь, надана для структури файлу / проекту, є абсолютно правильною.)

Також ..

На додаток до належного налаштування структури файлу проекту, ми повинні сказати flask шукати відповідний рівень ієрархії каталогів.

наприклад..

    app = Flask(__name__, template_folder='../templates')
    app = Flask(__name__, template_folder='../templates', static_folder='../static')

Починаючи з ../переміщення одного каталогу назад і починається там.

Починаючи з ../../переміщення двох каталогів назад і починається там (і так далі ...).

Сподіваюся, це допомагає


4

Не знаю чому, але натомість мені довелося використовувати таку структуру папок. Я ставлю "шаблони" на один рівень вище.

project/
    app/
        hello.py
        static/
            main.css
    templates/
        home.html
    venv/

Це, мабуть, свідчить про помилкову конфігурацію в іншому місці, але я не міг зрозуміти, що це було, і це спрацювало.


3

Перевірте, що:

  1. файл шаблону має правильну назву
  2. файл шаблону знаходиться у підкаталозі templates
  3. ім'я, якому ви render_templateпередаєте, відносно каталогу шаблонів ( index.htmlбуде безпосередньо в каталозі шаблонів, auth/login.htmlбуде в каталозі auth у каталозі шаблонів.)
  4. у вас або немає підкаталогу з тим самим іменем, що і ваш додаток, або каталог шаблонів знаходиться всередині цього підкаталогу.

Якщо це не спрацює, увімкніть налагодження ( app.debug = True), яке може допомогти зрозуміти, що не так.


3

Якщо ви запускаєте свій код із встановленого пакету, переконайтесь, що файли шаблонів присутні в каталозі <python root>/lib/site-packages/your-package/templates.


Деякі деталі:

У моєму випадку я намагався запустити приклади проекту flask_simple_ui і jinjaзавжди говорив

jinja2.exceptions.TemplateNotFound: form.html

Фокус у тому, що зразок програми імпортував встановлений пакет flask_simple_ui. І ninjaвикористання зсередини цього пакету використовує як кореневий каталог для пошуку шляху до пакету, у моєму випадку ...python/lib/site-packages/flask_simple_ui, замість того, os.getcwd() як можна було б очікувати.

На моє нещастя, setup.pyмає помилку і не копіює жодні файли html, включаючи відсутні form.html. Як тільки я виправив setup.py, проблема з TemplateNotFound зникла.

Сподіваюся, це комусь допоможе.


2

У мене була та сама помилка, виявляється, єдине, що я зробив неправильно, - це назвати мою папку 'шаблони', 'шаблон' без 's'. Змінивши, що він працював нормально, не знаю, чому це річ, але це так.


2

Коли використовується функція render_template (), вона намагається шукати шаблон у папці, що називається templates, і видає помилку jinja2.exceptions.TemplateNotFound, коли:

  1. файл html не існує або
  2. коли папка шаблонів не існує

Щоб вирішити проблему:

створити папку з шаблонами імен у тому самому каталозі, де знаходиться файл python, та розмістити HTML-файл, створений у папці шаблонів.


1

Вам потрібно помістити всі .htmlфайли в папку шаблону поруч із модулем python. І якщо у ваших файлах html є якісь зображення, які ви використовуєте, вам потрібно помістити всі файли в папку з назвою static

У наступній структурі

project/
    hello.py
    static/
        image.jpg
        style.css
    templates/
        homepage.html
    virtual/
        filename.json

1

Інша альтернатива - встановити, root_pathщо вирішує проблему як для шаблонів, так і для статичних папок.

root_path = Path(sys.executable).parent if getattr(sys, 'frozen', False) else Path(__file__).parent
app = Flask(__name__.split('.')[0], root_path=root_path)

Якщо ви рендеріть шаблони безпосередньо через Jinja2, ви пишете:

ENV = jinja2.Environment(loader=jinja2.FileSystemLoader(str(root_path / 'templates')))
template = ENV.get_template(your_template_name)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.