Jinja2无法在自定义内部服务器错误页面中呈现current_user

问题描述 投票:0回答:1

目前,我正在学习Miguel Grinberg编写的Flask with Flask mega教程。我没有验证用户的新用户名来测试自定义错误页面。问题是服务器无法返回500个错误代码的自定义错误页面,但它可以处理404错误代码。在回溯中,我注意到Jinja2的current_user存在问题。结果,服务器返回标准500错误页面。

用户加载器:

@login.user_loader
def load_user(user_id):
    cur_user = User.query.get(int(user_id))
    return cur_user

用户模型:

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))
    about_me = db.Column(db.String(140))
    last_seen = db.Column(db.DateTime, default=datetime.utcnow)

查看功能:

@app.route('/edit_profile', methods=['GET', 'POST'])
def edit_profile():
    form = EditProfileForm()
    if form.validate_on_submit():
        current_user.username = form.username.data
        current_user.about_me = form.about_me.data
        db.session.add(current_user)
        db.session.commit()
        flash('Your changes have been saved')
        return redirect(url_for('edit_profile'))
    elif request.method == 'GET':
        form.username.data = current_user.username
        form.about_me.data = current_user.about_me
    return render_template('edit_profile.html', title='Edit Profile', form=form)

错误处理程序:

@app.errorhandler(500)
def internal_error(error):
    return render_template('500.html'), 500

500.html

{% extends 'base.html' %}

{% block content %}
    <h1>An unexpected error has occurred.</h1>
    <p>The administrator has been notified. Sorry for the inconvenience.</p>
    <p><a href="{{ url_for('index') }}">Back</a></p>
{% endblock %}

base.html

<html>
    <head>
        {% if title %}
        <title>{{ title }} - Microblog</title>
        {% else %}
        <title>Welcome to Microblog</title>
        {% endif %}
    </head>
    <body>
        <div>
            Microblog:
            <a href="{{ url_for('index') }}">Home</a>
            {% if current_user.is_anonymous %}
            <a href="{{ url_for('login') }}">Login</a>
            {% else %}
            <a href="{{ url_for('user', username=current_user.username) }}">Profile</a>
            <a href="{{ url_for('logout') }}">Logout</a>
            {% endif %}
        </div>
        <hr>
        {% with messages = get_flashed_messages() %}
        {% if messages %}
        <ul>
            {% for message in messages %}
            <li>{{ message }}</li>
            {% endfor %}
        </ul>
        {% endif %}
        {% endwith %}
        {% block content %}{% endblock %}
    </body>
</html>

追踪:

Traceback (most recent call last):
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\werkzeug\serving.py", line 303, in run_wsgi
    execute(self.server.app)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\werkzeug\serving.py", line 291, in execute
    application_iter = app(environ, start_response)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\flask\app.py", line 2463, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\flask\app.py", line 2449, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\flask\app.py", line 1878, in handle_exception
    server_error = handler(server_error)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\app\errors.py", line 12, in internal_error
    return render_template('500.html'), 500
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\flask\templating.py", line 140, in render_template
    ctx.app,
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\flask\templating.py", line 120, in _render
    rv = template.render(context)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\jinja2\asyncsupport.py", line 76, in render
    return original_render(self, *args, **kwargs)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\jinja2\environment.py", line 1008, in render
    return self.environment.handle_exception(exc_info, True)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\jinja2\environment.py", line 780, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\jinja2\_compat.py", line 37, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\app\templates\500.html", line 1, in top-level template code
    {% extends 'base.html' %}
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\app\templates\base.html", line 16, in top-level template code
    <a href="{{ url_for('user', username=current_user.username) }}">Profile</a>
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\jinja2\environment.py", line 430, in getattr
    return getattr(obj, attribute)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\attributes.py", line 282, in __get__
    return self.impl.get(instance_state(instance), dict_)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\attributes.py", line 705, in get
    value = state._load_expired(state, passive)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\state.py", line 660, in _load_expired
    self.manager.deferred_scalar_loader(self, toload)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\loading.py", line 979, in load_scalar_attributes
    only_load_props=attribute_names,
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\loading.py", line 208, in load_on_ident
    identity_token=identity_token,
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\loading.py", line 282, in load_on_pk_identity
    return q.one()
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\query.py", line 3292, in one
    ret = self.one_or_none()
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\query.py", line 3261, in one_or_none
    ret = list(self)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\query.py", line 3334, in __iter__
    return self._execute_and_instances(context)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\query.py", line 3356, in _execute_and_instances
    querycontext, self._connection_from_session, close_with_result=True
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\query.py", line 3371, in _get_bind_args
    mapper=self._bind_mapper(), clause=querycontext.statement, **kw
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\query.py", line 3349, in _connection_from_session
    conn = self.session.connection(**kw)
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\session.py", line 1124, in connection
    execution_options=execution_options,
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\session.py", line 1130, in _connection_for_bind
    engine, execution_options
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\session.py", line 408, in _connection_for_bind
    self._assert_active()
  File "C:\Users\Georgiy\PycharmProjects\flask_microblog\venv\lib\site-packages\sqlalchemy\orm\session.py", line 295, in _assert_active
    code="7s2a",
sqlalchemy.exc.InvalidRequestError: This Session's transaction has been rolled back due to a previous exception during flush. To begin a new transaction with this Session, first issue Session.rollback(). Original exception was: (sqlite3.IntegrityError) UNIQUE constraint failed: user.username
[SQL: UPDATE user SET username=?, about_me=? WHERE user.id = ?]
[parameters: ('admin', "hello my name is Georgiy. I'm learning programming.", 2)]
(Background on this error at: http://sqlalche.me/e/gkpj) (Background on this error at: http://sqlalche.me/e/7s2a)

python-3.x flask jinja2 flask-sqlalchemy flask-login
1个回答
0
投票

您需要将FLASK_DEBUG环境变量设置为0才能触发自定义500错误处理程序。否则,您将看到调试器的回溯。

"If you set FLASK_DEBUG=0 in your terminal session and then trigger the duplicate username bug one more time, you are going to see a slightly more friendly error page"

https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-vii-error-handling

© www.soinside.com 2019 - 2024. All rights reserved.