
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
创建数据库迁移脚本
生成
manager.py
用于管理数据库版本from flask_script import Manager
from common.exts import db
from flask_migrate import MigrateCommand, Migrate
from app import app
# 导入Manager并绑定app
manager = Manager(app)
# 导入flaks_migrate
# Migrate 绑定app,db
Migrate(app, db)
# MigrateCommand 可以使用Alembic的命令
#
manager.add_command('db', MigrateCommand) # db是别名
if __name__ == '__main__':
manager.run()测试,并生成数据库版本
$ python manager.py db --help
$ python manager.py db init
$ python manager.py db migrate
$ python manager.py db upgrade查看数据库
mysql root@192.168.0.101:flask_login_demo1> show tables;
+-----------------------------+
| Tables_in_flask_login_demo1 |
+-----------------------------+
| alembic_version |
| users |
+-----------------------------+
2 rows in set
Time: 0.026s
运行程序,并注册账户
运行并测试程序.
尝试注册一个用户,并在数据库中查看
mysql root@192.168.0.101:flask_login_demo1> select * from users;
+----+-------------------+----------+--------------------------------------------------------------+-----------+
| id | email | username | _password_hash | confirmed |
+----+-------------------+----------+--------------------------------------------------------------+-----------+
| 1 | admin@foxmail.com | admin | $2b$12$bS4hsyeeqawgd.bmT2Z4ku.gNox02T6HKXzsWRIezm98HpIGKXegq | 0 |
+----+-------------------+----------+--------------------------------------------------------------+-----------+可以看到密码是密文存储在服务器上的.
然后尝试在未登录的情况下访问
http://127.0.0.1:5000/auth/personal/
,它会返回一个错误页面.它是401
错误,我们在errors.py
中添加一下401
错误.# 设计401, 403, 404, 500错误
@common_bp.app_errorhandler(401) # 未授权错误
def unauthorized(e):
return render_template('401.html'), 401
添加session
存储和过期时间操作
# views.py
@auth_bp.route('/login/', methods = ['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
"""登录用户"""
email = form.email.data.lower()
password = form.password.data
confirmed = form.confirmed.data
user = User.query.filter_by(email=email).first()
# 数据库中有账户,并且能够验证密码
if user is not None and user.check_password(password):
print(confirmed)
if confirmed:
login_user(user, remember=True, duration=timedelta(days=30))
else:
login_user(user)
# 判断 next
next = request.args.get('next')
if next is None or not next.startswitch('/'):
next = redirect(url_for('auth.index'))
return redirect(url_for('auth.personal' or next))
else:
flash('无效的邮箱或密码.')
return render_template('auth/login.html')
设置发送邮件注册
使用
Flask Mail
配置邮箱,在用户注册时,发送一个注册邮件给用户.# config.py
# 设置邮箱
MAIL_SERVER = 'smtp.qq.com'
MAIL_PORT = 465
MAIL_USERNAME = '257@qq.com'
MAIL_PASSWORD = "imkzffddijc"
MAIL_USE_SSL = True
MAIL_USE_TLS = False
MAIL_DEFAULT_SENDER = '257@qq.com'配置
app
# exts .py
from flask_mail import Mail
mail = Mail()# app.py
from common.exts import mail
mail.init_app(app)# mailModel.py
from flask_mail import Message
from flask import render_template, current_app
from threading import Thread
from common.exts import mail
# 异步发送邮件
def async_send_mail(app, msg):
# 要求在Flask的一次访问中发送邮件,下面代码中新建的线程中并
# 不包含 上下文结构,手动推送
with app.app_context():
mail.send(msg)
def sendMail(to, subject, template, **kwargs):
try:
# 创建邮件
msg = Message(subject, recipients=[to])
# 回传浏览器
msg.body = render_template('auth/mail/'+ template + '.txt', **kwargs)
msg.html = render_template('auth/mail/' + template + '.html', **kwargs)
print('auth/mail/{}'.format(template) + '.txt')
print('auth/mail/{}'.format(template) + '.html')
# 创建一个新线程,发送邮件
# 根据flask上下文,如果不再同一个 app 中,将无法发送邮件
app = current_app._get_current_object()
thread = Thread(target=async_send_mail, args=[app, msg])
thread.start()
return thread
except Exception as e:
print(e)更新视图
#views.py
from . import auth_bp
from flask import render_template, redirect, url_for, request, flash
from .auth_form import LoginForm, RegisterForm
from common.exts import db
from common.sqlModel import User
from flask_login import login_user, login_required, current_user
from datetime import timedelta
from common.mailModel import sendMail
@auth_bp.route('/')
def index():
return render_template('auth/index.html')
# 设计注册,登录页面
@auth_bp.route('/register/', methods = ['GET', 'POST'])
def register():
form = RegisterForm()
if form.validate_on_submit():
"""注册账户"""
email = form.email.data.lower()
username = form.username.data
password = form.password.data
user = User(email, username, password)
db.session.add(user)
db.session.commit()
# 生成发送邮件token
token = user.generate_confirmation_token()
# 将token发送到用户邮箱中,我们希望用户的激活形式为 http://xx.com/auth/confirm/<token>
sendMail(user.email, '激活账户', 'confirm', user=user, token=token)
flash("请通过注册邮箱激活账户!")
return redirect(url_for('auth.login'))
return render_template('auth/register.html')
@auth_bp.route('/login/', methods = ['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
"""登录用户"""
email = form.email.data.lower()
password = form.password.data
confirmed = form.confirmed.data
user = User.query.filter_by(email=email).first()
# 数据库中有账户,并且能够验证密码
if user is not None and user.check_password(password):
# print(confirmed)
if confirmed:
login_user(user, remember=True, duration=timedelta(days=30))
else:
login_user(user)
# 判断 next
next = request.args.get('next')
if next is None or not next.startswitch('/'):
next = redirect(url_for('auth.index'))
return redirect(url_for('auth.personal' or next))
else:
flash('无效的邮箱或密码.')
return render_template('auth/login.html')
# 限制登录用户访问 login_required
@auth_bp.route('/personal/')
@login_required
def personal():
return render_template('auth/personal.html', user = current_user)
# 设置激活邮件的路由
@auth_bp.route('/confirm/<token>')
@login_required
def confirm(token):
# flask_login可以通过 current_user 代理访问用户
# 激活的账户直接跳转到 index 页面
if current_user.confirmed:
return redirect(url_for('auth.index'))
# 验证序列化token
if current_user.check_confirmation_token(token):
# 设置数据库标志位为 True
db.session.commit()
flash('您的账户已激活,请登录!')
else:
flash('激活链接不正确或已过期!')
return redirect(url_for('auth.index'))
# 如果激活过期,再次发送激活邮件
@auth_bp.route('/confirm/')
@login_required
def resend_confirmation():
token = current_user.generate_confirmation_token()
sendMail(current_user.email, '激活账户', 'confirm', user=current_user, token=token)
flash("一个新的激活连接已通过邮箱发送给您,请点击激活!")
return redirect(url_for('auth.index'))
@auth_bp.route('/logout/')
@login_required
def logout():
return redirect(url_for('auth.index'))需要注意的是
flash()
消息要在前端接收一下.{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %}
{% endwith %}
– END –
原文始发于微信公众号(Flask学习笔记):Flask账户注册(3)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/36404.html