Flask
账户注册
综合使用所学习过的知识,搭建登录页面
代码示例:
https://github.com/ningwenyan/demo_code/tree/master/flask_demo_code/T26
总览
❯ tree
.
├── app.py
├── auth
│ ├── auth_form.py
│ ├── __init__.py
│ └── views.py
├── common
│ ├── errors.py
│ ├── exts.py
│ ├── __init__.py
│ ├── mailModel.py
│ └── sqlModel.py
├── config.py
├── manager.py
├── migrations
│ ├── alembic.ini
│ ├── env.py
│ ├── README
│ ├── script.py.mako
│ └── versions
│ ├── 44bc21866b0d_.py
│ └── __pycache__
│ └── 44bc21866b0d_.cpython-37.pyc
├── static
└── templates
├── 401.html
├── 403.html
├── 404.html
├── 500.html
└── auth
├── change_email.html
├── change_password.html
├── index.html
├── login.html
│ ├── change_email.html
│ ├── change_email.txt
│ ├── confirm.html
│ ├── confirm.txt
│ ├── password_reset.html
│ └── password_reset.txt
├── main
│ └── reset_password.html
├── personal.html
├── register.html
└── reset_password.html
设计修改密码
修改密码很容易,只要在登录的状态下,设计一个表单来修改即可.
<!----auth/change_password.html---->
<h3>Change Password</h3>
<form action="" method="post">
{# 解决csrf_token #}
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div>
<label for="">Old Password:</label>
<input type="password" placeholder="old password" name="old_password">
</div>
<div>
<label for="">New Password:</label>
<input type="password" placeholder="new password" name="new_password">
</div>
<div>
<label for="">Repeat Password:</label>
<input type="password" placeholder="repeat Password" name="rep_password">
</div>
<div><input type="submit" value="change"></div>
</form>设计表单
# auth_form.py
# 修改密码表单
class ChangePasswordForm(FlaskForm):
old_password = PasswordField(validators=[Length(1, 24)])
new_password = PasswordField(validators=[Length(1, 24)])
rep_password = PasswordField(validators=[EqualTo('new_password')])修改视图
# 修改密码
@auth_bp.route('/change_password', methods = ['GET', 'POST'])
@login_required
def change_password():
form = ChangePasswordForm()
if form.validate_on_submit():
old_password = form.old_password.data
new_password = form.new_password.data
if current_user.check_password(old_password):
# 解密验证旧密码
current_user.password = new_password
db.session.add(current_user)
db.session.commit()
flash("您的密码已修改.")
return redirect(url_for('auth.login'))
else:
flash("请输入正确的原密码.")
return render_template('auth/change_password.html')在
personal.html
中添加修改密码<p><a href="{{ url_for('auth.change_password') }}">修改密码</a> </p>
登录验证:通过
personal.html
验证修改密码.需要注意的是current_user
代理可以直接访问到用户.
增加忘记密码功能
新增加一个路由用于忘记密码时重置密码.它会给的注册邮箱发送一个带
token
连接用于修改密码
login.html
新增加一个忘记密码的超链接<!---login.html-->
<p><a href="{{ url_for('auth.reset_password_request') }}">Forget Password</a> </p>设计路由
# 设置忘记密码
@auth_bp.route('/reset_password/', methods= ['GET', 'POST'])
def reset_password_request():
form = ResetPasswordRequestForm()
if form.validate_on_submit():
email = form.email.data.lower()
user = User.query.filter(User.email == email).first()
if user is not None:
# 如果数据库中存在user,就发送重置密码的邮件
# 在数据库中重新创建一个 generate_reset_password_token 用于生成密码token
token = user.generate_reset_password_token()
# 发送邮件
sendMail(user.email, '重置密码', 'password_reset', user=user, token=token)
flash("请检查您的邮箱重置密码.")
return redirect(url_for('auth.login'))
return render_template('auth/reset_password.html')
reset_password.html
中只包含一个内容,就是填写邮箱<!-----reset_password---->
<h3>Reset Password</h3>
<form action="" method="post">
{# 解决csrf_token #}
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div>
<label for="">Email:</label>
<input type="text" placeholder="email" name="email">
</div>
<input type="submit" name="Send Email">
</form>我们将通过其中的
token
,这里会新增加一个方法# sqlModel.py
# 生成 reset password token
def generate_reset_password_token(self, expiration=3600):
s = Serializer(current_app._get_current_object().config['SECRET_KEY'], expires_in=expiration)
return s.dumps({'reset':self.id}).decode('utf-8')这样,我们就会发送一个邮件给注册邮箱,它的内容也比较简单,它会带
token
跳转到填写密码的页面# views.py
# 忘记密码,带token
@auth_bp.route('/reset_password/<token>', methods=['GET', 'POST'])
def reset_password(token):
form = ResetPasswordForm()
if form.validate_on_submit():
new_password = form.password.data
# 使用类方法验证token
if User.check_reset_password(token, new_password):
db.session.commit()
flash("您的密码已更新!")
return redirect(url_for('auth.login'))
else:
flash("您的账户不存在,请注册!")
return redirect(url_for('auth.register'))
return render_template('auth/main/reset_password.html')这里的
check_reset_password
是新定义的方法# sqlModel.py
# 序列化消息并验证,这里使用静态方法,对比以上的类的方法
@staticmethod
def check_reset_password(token, new_password):
s = Serializer(current_app._get_current_object().config['SECRET_KEY'])
try:
data = s.loads(token.encode('utf-8'))
except:
return False
user = User.query.get(data.get('reset'))
# 不是系统数据库中的用户,返回False
if user is None:
return False
user.password = new_password
db.session.add(user)
return True它使用的是静态方法,可以很方便的在
User
上操作,并设置一个新的密码.
设计修改邮箱
同样的方法,我们可以设计修改邮箱,它的好处是你必须是登录状态才能去修改邮箱.
先在
personal.html
添加一个跳转链接{# 修改邮箱 #}
<p><a href="{{ url_for('auth.change_email_request') }}">修改邮箱</a> </p>然后添加视图
# 修改邮箱
@auth_bp.route('/change_email/', methods = ['GET', 'POST'])
@login_required
def change_email_request():
form = ChangeEmailForm()
if form.validate_on_submit():
# 表单验证成功,并在数据库中不存在邮箱
password = form.password.data
new_email = form.new_email.data.lower()
if current_user.check_password(password):
token = current_user.generate_change_email_token(new_email)
sendMail(new_email, '更换新邮箱', 'change_email', user= current_user, token=token)
flash('您的邮箱已更换,请在新邮箱中激活账户.')
return redirect(url_for('auth.login'))
else:
flash('无效的邮箱或密码')
return render_template('auth/change_email.html')如上,我们需要设计一个新的
token
,专门为修改邮箱服务.它要包换原来的用户id
,以及新邮箱来确保它的唯一性.# 验证邮箱token的token
def generate_change_email_token(self,new_email, expiration=3600):
s = Serializer(current_app._get_current_object().config['SECRET_KEY'], expires_in=expiration)
return s.dumps({'email':self.id, 'new_email': new_email}).decode('utf-8')
def check_change_email_token(self, token):
s = Serializer(current_app._get_current_object().config['SECRET_KEY'])
try:
data = s.loads(token.encode('utf-8'))
except:
return False
new_email = data.get('new_email')
if data.get('email') != self.id:
return False
if new_email is None:
return False
# 判断重复
if self.query.filter_by(email = new_email).first() is not None:
return False
# 修改
self.email = new_email
db.session.add(self)
return True注意,我们的发送邮件的模板在
auth/mail/
下<p>您好,{{ user.username }}</p>
<p>点击<a href="{{ url_for('auth.change_email', token=token, _external=True) }}">修改</a>按钮修改你的账户.</p>
<p>您也可以双击以下连接激修改账户:</p>
<p>{{ url_for('auth.change_email', token=token, _external=True) }}</p>
<p>如果已修改,请忽略此邮件.</p>然后根据模板设计视图
@auth_bp.route('/change_email/<token>')
@login_required
def change_email(token):
if current_user.check_change_email_token(token):
db.session.commit()
flash('您的邮箱已修改.')
else:
flash("链接已过期,请重新修改邮箱.")
return redirect(url_for('auth.login'))
使用Flask Bootstrap
美化网页
– END –
原文始发于微信公众号(Flask学习笔记):Flask账户注册(4)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/36400.html