安装blinker、flask_login
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple flask_login
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple blinker
user_logged_in是signal实例

创建login_manager,继承lask_login.UserMixin的一些属性
app = Flask(__name__)
app.secret_key = 'super secret string'
app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
login_manager = flask_login.LoginManager()
login_manager.init_app(app)
password = '123'
class User(flask_login.UserMixin, db.Model):
__tablename__ = 'login_users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), nullable=False)
login_count = db.Column(db.Integer, default=0)
last_login_ip = db.Column(db.String(128), default='unknown')
db.create_all()
订阅信号
@flask_login.user_logged_in.connect_via(app)#信号订阅user_logged_in.connect(fn)
def _track_logins(sender, user, **extra):
print("_track_logins")
user.login_count += 1
user.last_login_ip = request.remote_addr
db.session.add(user)
db.session.commit()
发送信号并且记录用户用于后续判断用户状态
@app.route('/login', methods=['GET', 'POST'])
def login():
print("login")
if request.method == 'GET':
return '''
<form action='login' method='POST'>
<input type='text' name='name' id='name' placeholder='name'></input>
<input type='password' name='pw' id='pw' placeholder='password'></input>
<input type='submit' name='submit'></input>
</form>
'''
name = request.form.get('name')
if request.form.get('pw') == password:
user = User.query.filter_by(name=name).first()
if not user:
user = User(name=name)
db.session.add(user)
db.session.commit()
# 信号发送user_logged_in.send
# 提供给user_loader判断用户是否在登陆状态
flask_login.login_user(user)
return redirect(url_for('protected'))
内部实现发送信号的代码:
def login_user(user, remember=False, duration=None, force=False, fresh=True):
'''
Logs a user in. You should pass the actual user object to this. If the
user's `is_active` property is ``False``, they will not be logged in
unless `force` is ``True``.
This will return ``True`` if the log in attempt succeeds, and ``False`` if
it fails (i.e. because the user is inactive).
:param user: The user object to log in.
:type user: object
:param remember: Whether to remember the user after their session expires.
Defaults to ``False``.
:type remember: bool
:param duration: The amount of time before the remember cookie expires. If
``None`` the value set in the settings is used. Defaults to ``None``.
:type duration: :class:`datetime.timedelta`
:param force: If the user is inactive, setting this to ``True`` will log
them in regardless. Defaults to ``False``.
:type force: bool
:param fresh: setting this to ``False`` will log in the user with a session
marked as not "fresh". Defaults to ``True``.
:type fresh: bool
'''
if not force and not user.is_active:
return False
user_id = getattr(user, current_app.login_manager.id_attribute)()
session['user_id'] = user_id
session['_fresh'] = fresh
session['_id'] = current_app.login_manager._session_identifier_generator()
if remember:
session['remember'] = 'set'
if duration is not None:
try:
# equal to timedelta.total_seconds() but works with Python 2.6
session['remember_seconds'] = (duration.microseconds +
(duration.seconds +
duration.days * 24 * 3600) *
10**6) / 10.0**6
except AttributeError:
raise Exception('duration must be a datetime.timedelta, '
'instead got: {0}'.format(duration))
_request_ctx_stack.top.user = user
user_logged_in.send(current_app._get_current_object(), user=_get_user())
return True
user_loader根据login_user记录的用户检查相关登陆状态等信息
@login_manager.user_loader
def user_loader(id):
print("user_loader")
user = User.query.filter_by(id=id).first()
return user
完整的代码:
# coding=utf-8
from flask import Flask, request, redirect, url_for
import flask_login
from flask_sqlalchemy import SQLAlchemy
DB_HOSTNAME = 'localhost'
DATABASE_NAME = 'r'
DB_USERNAME = 'web'
DB_PASSWORD = 'web'
DB_PORT = 3306
# 'mysql://{}:{}@{}/{}'.format(
# USERNAME, PASSWORD, HOSTNAME, DATABASE)
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(DB_USERNAME, DB_PASSWORD, DB_HOSTNAME, DB_PORT, DATABASE_NAME)
app = Flask(__name__)
app.secret_key = 'super secret string'
app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
login_manager = flask_login.LoginManager()
login_manager.init_app(app)
password = '123'
class User(flask_login.UserMixin, db.Model):
__tablename__ = 'login_users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), nullable=False)
login_count = db.Column(db.Integer, default=0)
last_login_ip = db.Column(db.String(128), default='unknown')
db.create_all()
@flask_login.user_logged_in.connect_via(app)#信号订阅user_logged_in.connect(fn)
def _track_logins(sender, user, **extra):
print("_track_logins")
user.login_count += 1
user.last_login_ip = request.remote_addr
db.session.add(user)
db.session.commit()
@login_manager.user_loader
def user_loader(id):
print("user_loader")
user = User.query.filter_by(id=id).first()
return user
@app.route('/login', methods=['GET', 'POST'])
def login():
print("login")
if request.method == 'GET':
return '''
<form action='login' method='POST'>
<input type='text' name='name' id='name' placeholder='name'></input>
<input type='password' name='pw' id='pw' placeholder='password'></input>
<input type='submit' name='submit'></input>
</form>
'''
name = request.form.get('name')
if request.form.get('pw') == password:
user = User.query.filter_by(name=name).first()
if not user:
user = User(name=name)
db.session.add(user)
db.session.commit()
# 信号发送user_logged_in.send
# 提供给user_loader判断用户是否在登陆状态
flask_login.login_user(user)
return redirect(url_for('protected'))
return 'Bad login!'
@app.route('/protected')
@flask_login.login_required
def protected():
print("protected")
user = flask_login.current_user
return 'Logged in as: {}| Login_count: {}|IP: {}'.format(
user.name, user.login_count, user.last_login_ip)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=9001, debug=True)
本文介绍了如何安装并使用Flask-Login及其依赖binker来处理用户登录的信号。通过订阅user_logged_in信号,可以在用户登录时执行特定操作,并利用user_loader检查用户的登录状态。
334

被折叠的 条评论
为什么被折叠?



