一. 忘记密码
思维导图:
系统识别用户的方案,选用第二种或第三种, 第一种不安全。我们这里选择第二种方法
二.first_or_404
在app/forms/auth.py增加EmailForm:
class EmailForm(Form):
email = StringField(validators=[DataRequired(), Length(min=8, max=64), Email(message='电子邮件格式错误')])
编写app/web/auth.py的forget_password_request视图函数:
@web.route('/reset/password', methods=['GET', 'POST'])
def forget_password_request():
form = EmailForm(request.form)
if request.method == 'POST':
if form.validate():
account_email = form.email.fata
user = User.query.filter_by(email=account_email).first_or_404() # 如果不存在,会抛异常, 即后面的代码不会再执行了
#
# user = User.query.filter_by(email = account_email).first()
# if user:
# pass
# else:
# flash('账号不存在')
return render_template('auth/forget_password_request.html', form=form)
first_or_404查询出来的是None的话, 会自动抛出异常。并且后面的代码不会继续执行。
三. callable可调用对象的意义 ( __ call __ )
我们来看一下first_or_404的源码:
class BaseQuery(orm.Query):
"""SQLAlchemy :class:`~sqlalchemy.orm.query.Query` subclass with convenience methods for querying in a web application.
This is the default :attr:`~Model.query` object used for models, and exposed as :attr:`~SQLAlchemy.Query`.
Override the query class for an individual model by subclassing this and setting :attr:`~Model.query_class`.
"""
def get_or_404(self, ident):
"""Like :meth:`get` but aborts with 404 if not found instead of returning ``None``."""
rv = self.get(ident)
if rv is None:
abort(404)
return rv
def first_or_404(self):
"""Like :meth:`first` but aborts with 404 if not found instead of returning ``None``."""
rv = self.first()
if rv is None:
abort(404)
return rv
···
first_or_404是flask_sqlalchemy的BaseQuery的方法, 我们继续看一下first_or_404中abort方法:
def abort(status, *args, **kwargs):
'''
Raises an :py:exc:`HTTPException` for the given status code or WSGI
application::
abort(404) # 404 Not Found
abort(Response('Hello World'))
Can be passed a WSGI application or a status code. If a status code is
given it's looked up in the list of exceptions and will raise that
exception, if passed a WSGI application it will wrap it in a proxy WSGI
exception and raise that::
abort(404)
abort(Response('Hello World'))
'''
return _aborter(status, *args, **kwargs) #_aborter是一个对象,