使用Flask實現郵箱驗證啟用和使用者管理功能
阿新 • • 發佈:2019-01-31
Flask實現的功能:
- 使用者註冊增加郵箱驗證啟用功能
- 增加使用者管理功能(登入和登出)
目錄結構:
使用者註冊增加郵箱驗證啟用功能
1.user模型更新:
# 生成賬戶啟用的token
def generate_activate_token(self, expires_in=3600):
s = Serializer(current_app.config['SECRET_KEY'], expires_in=expires_in)
return s.dumps({'id': self.id})
# 賬戶啟用(靜態方法)
@staticmethod
def check_activate_token(token):
s = Serializer(current_app.config['SECRET_KEY'])
try:
data = s.loads(token)
except:
return False
u = User.query.get(data['id'])
if not u:
# 使用者已被刪除
return False
# 沒有啟用時才需要啟用
if not u.confirmed:
u.confirmed = True
db.session.add(u)
return True
2.views更新:
from app.email import send_mail
@user.route('/register/', methods=['GET', 'POST'])
def register():
...
# 下面生成token需要使用者id,此時還沒有id,需要手動提交
db.session.commit()
# 生成用於啟用校驗的token
token = u.generate_activate_token()
# 傳送啟用郵件到註冊郵箱
send_mail(u.email, '賬戶啟用', 'activate', username=u.username, token=token)
# 提示使用者下一步操作
flash('註冊成功,請移步至郵箱點選啟用')
# 跳轉到指定位置
return redirect(url_for('main.index'))
return render_template('user/register.html', form=form)
# 賬戶啟用
@user.route('/activate/<token>')
def activate(token):
if User.check_activate_token(token):
flash('啟用成功')
return redirect(url_for('user.login'))
else:
flash('啟用失敗')
return redirect(url_for('main.index'))
# 使用者登入
@user.route('/login/', methods=['GET', 'POST'])
def login():
...
elif not u.confirmed:
flash('賬戶尚未啟用,請啟用後再登入')
elif u.verify_password(form.password.data):
...
return render_template('user/login.html', form=form)
3.增加app目錄中email.py:
from flask import current_app, render_template
from app.extensions import mail
from flask_mail import Message
from threading import Thread
# 非同步傳送郵件
def async_send_mail(app, msg):
# 必須在程式上下文中才能傳送郵件,新建的執行緒沒有,因此需要手動建立
with app.app_context():
# 傳送郵件
mail.send(msg)
# 封裝函式傳送郵件
def send_mail(to, subject, template, **kwargs):
# 獲取原始的app例項
app = current_app._get_current_object()
# 建立郵件物件
msg = Message(subject, recipients=[to], sender=app.config['MAIL_USERNAME'])
# 瀏覽器接收顯示內容
msg.html = render_template('email/'+template+'.html', **kwargs)
# 終端接收顯示內容
msg.body = render_template('email/'+template+'.txt', **kwargs)
# 建立執行緒,在新的執行緒中傳送郵件
thr = Thread(target=async_send_mail, args=[app, msg])
thr.start()
return thr
4.templates資料夾中增加email資料夾:
activate.html:
<h1>Hello {{ username }}</h1>
<p>啟用請點選右邊連結,<a href="{{ url_for('user.activate', token=token, _external=True) }}">啟用</a></p>
增加使用者管理功能(登入和登出)
1.在extensions.py中增加使用者管理庫:
from flask_login import LoginManager
login_manager = LoginManager()
def config_extensions(app):
...
login_manager.init_app(app)
2.views.py中增加使用者登入儲存物件和使用者登出檢視函式:
from flask_login import login_user, logout_user, login_required, current_user
@user.route('/login/',methods=['GET', 'POST'])
def login():
...
elif u.verify_password(form.password.data):
login_user(u, remember=form.remember.data)
flash('login success')
return redirect(request.args.get('next') or url_for('main.index'))
...
return render_template('user/login.html', form=form)
@user.route('/logout/')
def logout():
logout_user()
flash('logout success')
return redirect(url_for('main.index'))
3.修改main.py中的檢視函式,渲染模板中main/index.html:
from flask import Blueprint,render_template,redirect,url_for
main = Blueprint('main', __name__)
@main.route('/')
def index():
return render_template('main/index.html')
4.在模型user.py中,增加login的回撥函式:
# 登入認證的回撥
@login_manager.user_loader
def loader_user(uid):
return User.query.get(int(uid))
5.增加main/index.html模板:
{% extends 'common/base.html' %}{% block title %}首頁{% endblock %}{% block page_content %}{% if current_user.is_authenticated %}
<h1>hello! {{current_user.username}}</h1>
{% endif %}{% endblock %}
6.更新base.html模板,增加登入後的模板顯示內容:
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li><a href="#">板塊1</a></li>
<li><a href="#">板塊2</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
{% if current_user.is_authenticated %}
<li><a href="{{ url_for('user.logout') }}">退出</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">{{ current_user.username }} <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">個人資訊</a></li>
<li><a href="#">修改密碼</a></li>
<li><a href="#">修改郵箱</a></li>
<li><a href="#">修改頭像</a></li>
</ul>
</li>
{% else %}
<li><a href="{{ url_for('user.login') }}">登入</a></li>
<li><a href="{{ url_for('user.register') }}">註冊</a></li>
{% endif %}
</ul>
</div><!-- /.navbar-collapse -->