Flask làm tăng lỗi TemplateNotFound mặc dù tệp mẫu tồn tại


107

Tôi đang cố gắng kết xuất tệp home.html. Tệp tồn tại trong dự án của tôi, nhưng tôi vẫn nhận được jinja2.exceptions.TemplateNotFound: home.htmlkhi tôi cố gắng kết xuất nó. Tại sao Flask không thể tìm thấy mẫu của tôi?

from flask import Flask, render_template

app = Flask(__name__)

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

Câu trả lời:


212

Bạn phải tạo các tệp mẫu của mình ở đúng vị trí; trong templatesthư mục con bên cạnh mô-đun python của bạn.

Lỗi chỉ ra rằng không có home.htmltệp trong templates/thư mục. Đảm bảo rằng bạn đã tạo thư mục đó trong cùng thư mục với mô-đun python của mình và trên thực tế, bạn đã đặt một home.htmltệp vào thư mục con đó. Nếu ứng dụng của bạn là một gói, thì thư mục mẫu phải được tạo bên trong gói.

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

Ngoài ra, nếu bạn đặt tên thư mục mẫu của mình khác templatesvà không muốn đổi tên nó thành mặc định, bạn có thể yêu cầu Flask sử dụng thư mục khác đó.

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

Bạn có thể yêu cầu Flask giải thích cách nó đã cố gắng tìm một mẫu nhất định, bằng cách đặt EXPLAIN_TEMPLATE_LOADINGtùy chọn thành True. Đối với mỗi mẫu được tải, bạn sẽ nhận được một báo cáo được ghi vào Flaskapp.logger , ở cấp độ INFO.

Đây là giao diện khi tìm kiếm thành công; trong ví dụ này, foo/bar.htmlmẫu mở rộng base.htmlmẫu, vì vậy có hai tìm kiếm:

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

Bản thiết kế cũng có thể đăng ký các thư mục mẫu của riêng chúng , nhưng đây không phải là yêu cầu nếu bạn đang sử dụng bản thiết kế để dễ dàng phân chia một dự án lớn hơn thành các đơn vị logic. Thư mục mẫu ứng dụng Flask chính luôn được tìm kiếm đầu tiên ngay cả khi sử dụng các đường dẫn bổ sung cho mỗi bản thiết kế.


2
EXPLAIN_TEMPLATE_LOADING rất hữu ích để gỡ lỗi các vấn đề về đường dẫn xung quanh các mẫu. Ngoài ra, nếu bạn sử dụng Bản thiết kế, hãy đảm bảo bạn đặt template_folderđường dẫn cho mỗi bản thiết kế .
Justin Krause

1
@JustinKrause: cảm ơn vì những điều đó, EXPLAIN_TEMPLATE_LOADINGđã được thêm vào sau khi câu trả lời này được viết ban đầu.
Martijn Pieters

1
Có vẻ như bình cục bộ của tôi (trên Windows) có thể tìm thấy các mẫu bên trong ./Templates/index.html, nhưng khi tôi triển khai lên heroku (nghĩ rằng nó giống Python, cùng một phiên bản thư viện, bao gồm cùng một phiên bản Flask; nhưng heroku là Unix); và ném TemplateNotFoundlỗi; sau khi tôi đổi tên thư mục git mv Templates/index.html templates/index.html, cả hai địa phương (Windows) và Heroku (Unix) phiên bản làm việc
The Red Pea

1
@TheRedPea vâng, bởi vì hệ thống tệp Windows gấp trường hợp nên Templates== templates. Nhưng Heroku chạy Linux, với hệ thống tệp phân biệt chữ hoa chữ thường.
Martijn Pieters

11

Tôi nghĩ Flask sử dụng các mẫu thư mục theo mặc định. Vì vậy, mã của bạn nên giả sử đây là 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)

Và bạn cấu trúc không gian làm việc như

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

Ngoài ra, bạn đã tạo hai tệp html với tên home.html và about.html và đặt các tệp đó trong thư mục mẫu.


8

(Xin lưu ý rằng Câu trả lời được chấp nhận ở trên được cung cấp cho cấu trúc tệp / dự án là hoàn toàn chính xác.)

Cũng thế..

Ngoài việc thiết lập đúng cấu trúc tệp dự án, chúng ta phải yêu cầu flask xem xét mức độ phù hợp của hệ thống phân cấp thư mục.

ví dụ..

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

Bắt đầu với việc ../di chuyển ngược một thư mục và bắt đầu ở đó.

Bắt đầu với việc ../../di chuyển hai thư mục ngược lại và bắt đầu ở đó (và như vậy ...).

Hi vọng điêu nay co ich


4

Tôi không biết tại sao, nhưng tôi đã phải sử dụng cấu trúc thư mục sau để thay thế. Tôi đặt "mẫu" lên một cấp.

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

Điều này có thể chỉ ra một cấu hình sai ở nơi khác, nhưng tôi không thể tìm ra đó là gì và điều này đã hoạt động.


3

Kiểm tra xem:

  1. tệp mẫu có tên phù hợp
  2. tệp mẫu nằm trong thư mục con được gọi là templates
  3. tên bạn chuyển đến render_templatecó liên quan đến thư mục mẫu ( index.htmlsẽ nằm trực tiếp trong thư mục mẫu, auth/login.htmlsẽ nằm dưới thư mục auth trong thư mục mẫu.)
  4. bạn không có thư mục con có cùng tên với ứng dụng của mình hoặc thư mục mẫu nằm bên trong thư mục con đó.

Nếu cách đó không hiệu quả, hãy bật gỡ lỗi ( app.debug = True) để giúp tìm ra vấn đề.


3

Nếu bạn chạy mã của mình từ một gói đã cài đặt, hãy đảm bảo rằng các tệp mẫu có trong thư mục <python root>/lib/site-packages/your-package/templates.


Một số chi tiết:

Trong trường hợp của tôi, tôi đang cố gắng chạy các ví dụ về dự án flask_simple_uijinjasẽ luôn nói

jinja2.exceptions.TemplateNotFound: form.html

Bí quyết là chương trình mẫu sẽ nhập gói đã cài đặt flask_simple_ui. Và ninjaviệc được sử dụng từ bên trong gói đó được sử dụng làm thư mục gốc để tra cứu đường dẫn gói, trong trường hợp của tôi ...python/lib/site-packages/flask_simple_ui, thay vì os.getcwd() như người ta mong đợi.

Thật không may, setup.pycó một lỗi và không sao chép bất kỳ tệp html nào, kể cả tệp bị thiếu form.html. Sau khi tôi khắc phục setup.py, sự cố với TemplateNotFound đã biến mất.

Tôi hi vọng nó giúp ích cho ai đó.


2

Tôi đã gặp cùng một lỗi, hóa ra điều duy nhất tôi đã làm sai là đặt tên cho thư mục 'mẫu' của mình, 'mẫu' mà không có 's'. Sau khi thay đổi mà nó hoạt động tốt, không biết tại sao nó là một điều nhưng nó là.


2

Khi hàm render_template () được sử dụng, nó sẽ cố gắng tìm kiếm mẫu trong thư mục được gọi là mẫu và nó sẽ ném ra lỗi jinja2.exceptions.TemplateNotFound khi:

  1. tệp html không tồn tại hoặc
  2. khi thư mục mẫu không tồn tại

Để giải quyết vấn đề:

tạo một thư mục với các mẫu tên trong cùng một thư mục chứa tệp python và đặt tệp html đã tạo trong thư mục mẫu.


1

Bạn cần đặt tất cả .htmlcác tệp của mình vào thư mục mẫu bên cạnh mô-đun python của bạn. Và nếu có bất kỳ hình ảnh nào bạn đang sử dụng trong các tệp html của mình thì bạn cần đặt tất cả các tệp của mình vào thư mục có tên tĩnh

Trong cấu trúc sau

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

1

Một giải pháp thay thế khác là đặt giải pháp root_pathkhắc phục sự cố cho cả mẫu và thư mục tĩnh.

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

Nếu bạn hiển thị các mẫu trực tiếp qua Jinja2, thì bạn viết:

ENV = jinja2.Environment(loader=jinja2.FileSystemLoader(str(root_path / 'templates')))
template = ENV.get_template(your_template_name)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.