centos7服务器渲染页面时报错jinja2.exceptions.TemplateNotFound: bootstrap/wtf.HTML?

使用相同的Python版本3.7,在本地运行渲染页面无异常,在centos服务器上渲染页面时报错jinja2.exceptions.TemplateNotFound: bootstrap/wtf.HTML

使用flask-bootstrap三方库
项目结构:
project:
APP

  - auth
      -views.py
      -forms.py
  -templates
    - auth
      - login.html
  -static
  - __init__.py

app.py
config.py

视图代码:views.py

from flask import render_template, redirect, request, url_for, flash, abort
from flask_login import login_required, login_user, logout_user, current_user
from . import auth
from .forms import LoginForm, RegistrationForm, ResetPasswordSendEmailForm, ResetNewPasswordForm, ChangePasswordForm, \
    ModifyEmailForm
from .. import db
from ..models import User

@auth.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data.lower()).first()
        if user is not None and user.verify_password(form.password.data):
            login_user(user, form.remember_me.data)
            _next = request.args.get('next')
            if _next is None or not _next.startswith('/'):
                _next = url_for('main.index')
            return redirect(_next)
        flash('Invalid username or password.')
    return render_template('auth/login.html', form=form)

表单代码:forms.py

from flask_wtf import FlaskForm
from wtforms import SubmitField, StringField, PasswordField, BooleanField
from wtforms.validators import DataRequired, Length, Email, Regexp, EqualTo, ValidationError

class LoginForm(FlaskForm):
    username = StringField('账号', validators=[DataRequired(), Length(1, 64)])
    password = PasswordField('密码', validators=[DataRequired()])
    remember_me = BooleanField('Keep me logged in')
    submit = SubmitField('登录')

登录静态页:login.html

{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title_content %}Login{% endblock %}

{% block page_content %}
    <div class="page-header">
        <h1>Login</h1>
    </div>
    <div class="col-md-4">
        {{ wtf.quick_form(form) }}
    </div>
{% endblock %}

工厂方法:__init__.py

from flask import Flask, render_template
from flask_bootstrap import Bootstrap
from flask_moment import Moment
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
from flask_pagedown import PageDown
from config import config

bootstrap = Bootstrap()
moment = Moment()
db = SQLAlchemy()
migrate = Migrate()
login_manager = LoginManager()
login_manager.session_protection = 'strong'
login_manager.login_view = 'auth.login'
pagedown = PageDown()


def create_app(config_name='default'):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)
    bootstrap.init_app(app) 
    moment.init_app(app)
    db.init_app(app)
    migrate.init_app(app, db)
    login_manager.init_app(app)
    pagedown.init_app(app)

    from .auth import auth as auth_blueprint
    app.register_blueprint(auth_blueprint, url_prefix='/auth')
    return app

启动入口代码:app.py

import os
from app import create_app, db
from app.models import User, Role
from flask_script import Manager, Shell

app = create_app(os.getenv('FLASK_CONFIG') or 'default')
manager = Manager(app)
COV = None
if os.environ.get('FLASK_COVERAGE'):
    import coverage
    COV = coverage.coverage(branch=True, include='app/*')
    COV.start()

@app.shell_context_processor
def make_shell_context():
    return dict(app=app, db=db, User=User, Role=Role)

@manager.command
def profile(length=25, profile_dir=None):
    """Start the application under the code profiler."""
    from werkzeug.middleware.profiler import ProfilerMiddleware
    app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[length], profile_dir=profile_dir)
    app.run()

manager.add_command('shell', Shell(make_context=make_shell_context))

if __name__ == '__main__':
    manager.run()

配置文件:config.py

import os

basedir = os.path.abspath(os.path.dirname(__file__))

class Config:
    SECRET_KEY = '234sdf*^&%sfjDS,.<DSF21!'
    SQLALCHEMY_COMMIT_ON_TEARDOWN = True
    FLASKY_POSTS_PER_PAGE = 10
    FLASKY_FOLLOWERS_PER_PAGE = 10
    FLASKY_COMMENTS_PER_PAGE = 10
    SQLALCHEMY_RECORD_QUERIES = True
    FLASKY_SLOW_DB_QUERY_TIME = 0.5
    ATTACHMENT_PATH = basedir + '/app/static'
    STATIC_PATH = basedir + '/app/static/HTML/'
    QR_CODE_PATH = basedir + '/app/static/QR/'

    @staticmethod
    def init_app(app):
        pass

class DevelopmentConfig(Config):
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.join(basedir, 'dev-data.sqlite')}"
    SQLALCHEMY_TRACK_MODIFICATIONS = True

config = {
    'development': DevelopmentConfig,
    'testing': TestingConfig,
    'production': ProductionConfig,
    'default': DevelopmentConfig
}

错误信息:

127.0.0.1 - - [16/Mar/2023 18:51:54] "GET / HTTP/1.0" 302 -
[2023-03-16 18:51:54,230] ERROR in app: Exception on /auth/login [GET]
Traceback (most recent call last):
  File "/root/.virtualenvs/venv/lib/python3.7/site-packages/flask/app.py", line 2528, in wsgi_app
    response = self.full_dispatch_request()
  File "/root/.virtualenvs/venv/lib/python3.7/site-packages/flask/app.py", line 1825, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/root/.virtualenvs/venv/lib/python3.7/site-packages/flask/app.py", line 1823, in full_dispatch_request
    rv = self.dispatch_request()
  File "/root/.virtualenvs/venv/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/home/sibleyAlloyWorkpieceSpecification/app/auth/views.py", line 43, in login
    return render_template('auth/login.html', form=form)
  File "/root/.virtualenvs/venv/lib/python3.7/site-packages/flask/templating.py", line 147, in render_template
    return _render(app, template, context)
  File "/root/.virtualenvs/venv/lib/python3.7/site-packages/flask/templating.py", line 130, in _render
    rv = template.render(context)
  File "/root/.virtualenvs/venv/lib/python3.7/site-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/root/.virtualenvs/venv/lib/python3.7/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "/home/sibleyAlloyWorkpieceSpecification/app/templates/auth/login.html", line 2, in top-level template code
    {% import "bootstrap/wtf.HTML" as wtf %}
  File "/root/.virtualenvs/venv/lib/python3.7/site-packages/flask/templating.py", line 61, in get_source
    return self._get_source_explained(environment, template)
  File "/root/.virtualenvs/venv/lib/python3.7/site-packages/flask/templating.py", line 88, in _get_source_explained
    raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: bootstrap/wtf.HTML
阅读 1.3k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进