1. 程式人生 > >使用Flask實現郵箱驗證啟用和使用者管理功能

使用Flask實現郵箱驗證啟用和使用者管理功能

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 -->