O Flask gera um erro TemplateNotFound, embora o arquivo de modelo exista

107

Estou tentando renderizar o arquivo home.html. O arquivo existe no meu projeto, mas continuo recebendo jinja2.exceptions.TemplateNotFound: home.htmlquando tento renderizá-lo. Por que o Flask não consegue encontrar meu modelo?

from flask import Flask, render_template

app = Flask(__name__)

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

Respostas:

212

Você deve criar seus arquivos de modelo no local correto; no templatessubdiretório próximo ao seu módulo python.

O erro indica que não há home.htmlarquivo no templates/diretório. Certifique-se de ter criado esse diretório no mesmo diretório de seu módulo python e de ter de fato colocado um home.htmlarquivo nesse subdiretório. Se seu aplicativo for um pacote, a pasta de modelos deve ser criada dentro do pacote.

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

Alternativamente, se você nomeou sua pasta de modelos de outra forma templatese não deseja renomeá-la para o padrão, você pode dizer ao Flask para usar esse outro diretório.

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

Você pode pedir ao Flask para explicar como tentou encontrar um determinado modelo, definindo a EXPLAIN_TEMPLATE_LOADINGopção para True. Para cada template carregado, você obterá um relatório registrado no Flaskapp.logger , no nível INFO.

Isso é o que parece quando uma pesquisa é bem-sucedida; neste exemplo, o foo/bar.htmlmodelo estende o base.htmlmodelo, portanto, há duas pesquisas:

[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')

Os blueprints também podem registrar seus próprios diretórios de modelo , mas isso não é um requisito se você estiver usando blueprints para facilitar a divisão de um projeto maior em unidades lógicas. O diretório principal do modelo do aplicativo Flask é sempre pesquisado primeiro, mesmo ao usar caminhos adicionais por blueprint.

Martijn Pieters
fonte
2
EXPLAIN_TEMPLATE_LOADING é muito útil para depurar problemas de caminho em torno de modelos. Além disso, se você usar Blueprints, certifique-se de definir o template_foldercaminho por blueprint .
Justin Krause
1
@JustinKrause: obrigado por aqueles, EXPLAIN_TEMPLATE_LOADINGfoi adicionado depois que esta resposta foi escrita inicialmente.
Martijn Pieters
1
Parece que meu flask local (no Windows) pode encontrar modelos dentro ./Templates/index.html, mas quando eu implantar no heroku (pensei que fosse o mesmo Python, mesmas versões de biblioteca, incluindo a mesma versão do Flask; mas heroku é Unix); e lança TemplateNotFounderro; depois de renomear a pasta git mv Templates/index.html templates/index.html, as versões local (Windows) e heroku (Unix) funcionaram
The Red Pea
1
@TheRedPea sim, porque o sistema de arquivos do Windows fecha a caixa então Templates== templates. Mas o Heroku roda Linux, com um sistema de arquivos que diferencia maiúsculas de minúsculas.
Martijn Pieters
11

Acho que o Flask usa os modelos de diretório por padrão. Portanto, seu código deve ser suposto que este é o seu 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)

E você trabalha a estrutura do espaço como

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

Além disso, você deve criar dois arquivos html com os nomes home.html e about.html e colocar esses arquivos na pasta de modelos.

Akshay Karande
fonte
8

(Observe que a Resposta aceita acima fornecida para a estrutura do arquivo / projeto está absolutamente correta.)

Além disso..

Além de configurar corretamente a estrutura do arquivo do projeto, temos que dizer ao flask para procurar no nível apropriado da hierarquia de diretórios.

por exemplo..

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

Começar com ../move um diretório para trás e começa aí.

Começar com ../../move dois diretórios para trás e começa aí (e assim por diante ...).

Espero que isto ajude

Ninguém
fonte
4

Não sei por que, mas tive que usar a seguinte estrutura de pastas. Eu coloquei "modelos" um nível acima.

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

Isso provavelmente indica uma configuração incorreta em outro lugar, mas não consegui descobrir o que era e funcionou.

François Breton
fonte
3

Verifique se:

  1. o arquivo de modelo tem o nome certo
  2. o arquivo de modelo está em um subdiretório chamado templates
  3. o nome que você passa render_templateé relativo ao diretório de modelos ( index.htmlestaria diretamente no diretório de modelos, auth/login.htmlestaria sob o diretório auth no diretório de modelos).
  4. você não tem um subdiretório com o mesmo nome de seu aplicativo ou o diretório de modelos está dentro desse subdiretório.

Se isso não funcionar, ative debugging ( app.debug = True) que pode ajudar a descobrir o que está errado.

Eric
fonte
3

Se você executar seu código de um pacote instalado, certifique-se de que os arquivos de modelo estejam presentes no diretório <python root>/lib/site-packages/your-package/templates.


Alguns detalhes:

No meu caso, eu estava tentando executar exemplos do projeto flask_simple_ui e jinjasempre dizia

jinja2.exceptions.TemplateNotFound: form.html

O truque era que o programa de amostra importaria o pacote instalado flask_simple_ui. E ninjaser usado de dentro desse pacote é usar como diretório raiz para pesquisar o caminho do pacote, no meu caso ...python/lib/site-packages/flask_simple_ui, em vez de os.getcwd() como seria de esperar.

Para meu azar, setup.pyestá com um bug e não copia nenhum arquivo html, inclusive o ausente form.html. Depois de consertar setup.py, o problema com TemplateNotFound desapareceu.

Eu espero que isso ajude alguém.

Yuriy Pozniak
fonte
2

Eu tive o mesmo erro, mas a única coisa que fiz de errado foi nomear minha pasta 'templates', 'template' sem 's'. Depois de mudar isso funcionou bem, não sei por que é uma coisa, mas é.

Shubham Khaire
fonte
2

Quando a função render_template () é usada, ela tenta pesquisar o modelo na pasta chamada modelos e gera o erro jinja2.exceptions.TemplateNotFound quando:

  1. o arquivo html não existe ou
  2. quando a pasta de modelos não existe

Para resolver o problema:

crie uma pasta com modelos de nomes no mesmo diretório onde o arquivo python está localizado e coloque o arquivo html criado na pasta de modelos.

Atal Kumar
fonte
1

Você precisa colocar todos os seus .htmlarquivos na pasta de modelos ao lado do seu módulo python. E se houver alguma imagem que você está usando em seus arquivos html, então você precisa colocar todos os seus arquivos na pasta chamada static

Na seguinte estrutura

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

Outra alternativa é definir o root_pathque corrige o problema tanto para modelos quanto para pastas estáticas.

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

Se você renderizar modelos diretamente via Jinja2, então você escreve:

ENV = jinja2.Environment(loader=jinja2.FileSystemLoader(str(root_path / 'templates')))
template = ENV.get_template(your_template_name)
Max
fonte