我有一个有趣的问题。基本上,我有这个Flask Restful API应用程序,在这里有一个HTML页面,登录用户可以在该页面上创建API用户。这是由SQLAlchemy模型类Apiusers处理的,我在其中使用validate修饰符来确保用户名和电子邮件地址遵守规则。所有这些都可以正常工作,当用户输入无效信息时,它会引发异常,但是无论如何我都无法在Flask中捕获它。我想捕获它并向用户闪回一条消息,但是相反,它抛出一个Builtins.AssertionError,最终在不处于调试模式时会给出500个内部服务器错误页面。
代码与此非常相似:https://nunie123.github.io/sqlalchemy-validation.html
尝试使用不同类型的异常-ValueError,定义自定义异常类,最后捕获所有带有except的错误:但是异常总是以无法处理的形式结束。我也遇到了一些类似的问题,如此处所述:https://github.com/marshmallow-code/webargs/issues/122,其中提到烧瓶烧瓶劫持了所有HTTP异常的处理,但这是从2016年开始的。无论哪种情况,我都能捕获SQLAlchemy唯一约束异常在使用验证之前在同一地点,所以我认为这不是问题。
models.py:
from sqlalchemy.orm import validates
class Apiusers(db.Model):
__tablename__ = 'apiusers'
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)
password_hash = db.Column(db.String(128))
def __repr__(self):
return self.username
@validates('username')
def validate_username(self, key, username):
if not username:
raise AssertError('No username provided')
if Apiusers.query.filter(Apiusers.username == username).first():
raise AssertError('Username is already in use')
if len(username) < 5 or len(username) > 20:
raise AssertError('Username must be between 5 and 20 characters')
return username
@validates('email')
def validate_email(self, key, email):
if not email:
raise AssertError('No email provided')
if not re.match("[^@]+@[^@]+\.[^@]+", email):
raise AssertError('Provided email is not an email address')
return email
views.py:
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
_user = request.form['username']
_email = request.form['emails']
record = Apiusers(username=_user, email=_email)
try:
db.session.add(record)
db.session.commit()
except AssertError as e:
flash('{}'.format(str(e)), 'danger')
return render_template("register.html")
return render_template("regresult.html")
以下是尝试添加空用户名时的堆栈跟踪:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 2309, in
__call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 2295, in
wsgi_app
response = self.handle_exception(e)
File "/usr/local/lib/python3.6/site-packages/flask_restful/__init__.py", line 269, in error_router
return original_handler(e)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.6/site-packages/flask_restful/__init__.py", line 269, in error_router
return original_handler(e)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/opt/app/api2/app.py", line 189, in regresult
record = Apiusers(username=_user, email=_email)
File "<string>", line 4, in __init__
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/state.py", line 428, in _initialize_instance
manager.dispatch.init_failure(self, args, kwargs)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 67, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 277, in reraise
raise value
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/state.py", line 425, in _initialize_instance
return manager.original_init(*mixed[1:], **kwargs)
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/ext/declarative/base.py", line 801, in _declarative_constructor
setattr(self, k, kwargs[k])
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/attributes.py", line 263, in __set__
instance_state(instance), instance_dict(instance), value, None
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/attributes.py", line 810, in set
state, dict_, value, old, initiator
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/attributes.py", line 818, in fire_replace_event
state, value, previous, initiator or self._replace_token
File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/util.py", line 168, in set_
return validator(state.obj(), key, value)
File "/opt/app/api2/app.py", line 95, in validate_name
assert value != '', "Invalid username"
AssertionError: Invalid username
答案 0 :(得分:0)
未处理的断言将导致程序终止。参见here。 试试类似的东西:
if not email:
flash('Your error message')
return redirect(request.url)
if not re.match("[^@]+@[^@]+\.[^@]+", email):
flash('Your error message')
return redirect(request.url)
答案 1 :(得分:0)
实际上只是想出了答案。 在try-except块中移动了调用Apiusers模型的代码行后,所有异常都被捕获并处理得很好:-) 以前,由于该行不在街区之外,因此最终无法处理。当您错过下午咖啡时,就会发生这种情况。
try:
record = Apiusers(username=_user, email=_email)
db.session.add(record)
db.session.commit()