如何从sqlalchemy@validate d捕获Flask中的异常

2024-05-18 14:21:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我有个有趣的问题。基本上我有一个Flask restful API应用程序,其中我有一个HTML页面,登录用户可以在该页面上创建API用户。这是由SQLAlchemy模型类Apiusers处理的,我在其中使用validates decorator来确保用户名和电子邮件地址遵守规则。所有的工作都很好,当用户输入无效信息时,它会抛出一个异常,但无论如何我都无法在烧瓶中捕捉到它。我想捕捉它并向用户闪回一条关于它的消息,但它却抛出了一个内置的.AssertionError当不在调试模式下时,它会给出500个内部服务器错误页。在

代码与此非常相似:https://nunie123.github.io/sqlalchemy-validation.html

尝试使用不同类型的异常-ValueError,定义自定义异常类,最后用except:捕获所有错误,但异常最终总是无法处理。我也遇到了类似的问题:https://github.com/marshmallow-code/webargs/issues/122其中提到flask restful劫持了所有HTTP异常的处理,但这是从2016年开始的。在任何一种情况下,我都能够在使用validates之前在同一个位置捕捉到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")

以下是尝试添加空用户名时的stacktrace:

^{pr2}$

Tags: 用户selftruedbreturnifemaildef
2条回答

事实上我刚刚找到了答案。 在try-except块中移动调用Apiusers模型的代码行之后,所有异常都被捕获并处理得很好:-) 以前,由于那条线在块外,所以它们最终无法处理。当你错过了下午的咖啡,就会发生这种事。在

try:
  record = Apiusers(username=_user, email=_email)
  db.session.add(record)
  db.session.commit()

未处理的断言将导致程序终止。见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)

相关问题 更多 >

    热门问题