说明

  • 操作系统:Windows 10
  • Python 版本:3.7x
  • 虚拟环境管理器:virtualenv
  • 代码编辑器:VS Code

实验目标

通过使用 flask-login 进行会话管理的相关操作,并完成用户合法性登陆和退出。

安装

pip install flask-login

使用

首先,在 todlist\app\__init__.py 中创建 login_manager,并进行相关配置,示例代码如下所示:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bootstrap import Bootstrap
from flask_login import LoginManager
from config import Config app = Flask(__name__)
app.config.from_object(Config) db = SQLAlchemy(app)
bootstrap = Bootstrap(app) login_manager = LoginManager(app)
login_manager.login_view = 'login'
login_manager.login_message = '你必须登陆后才能访问该页面'
login_manager.login_message_category = "info" from app import views

然后,完善我们 todolist\models.py 中关于用户密码校验部分的逻辑处理,示例代码如下所示:

from app import db, login_manager
from datetime import datetime
from werkzeug.security import check_password_hash, generate_password_hash
from flask_login import UserMixin, login_user @login_manager.user_loader
def load_user(user_id):
user = User.query.get(user_id)
return user class User(db.Model, UserMixin):
__tablename__ = 'users'
# __table_args__ = {"useexisting": True} id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(20), nullable=False, unique=True)
email = db.Column(db.String(120), nullable=False, unique=True)
pwd = db.Column(db.String(120), nullable=False) things = db.relationship('Thing', backref='User', lazy='dynamic') def __repr__(self):
return "<User %r>" % self.name def generate_password_hash(self, pwd):
self.pwd = generate_password_hash(pwd) def check_password_hash(self, pwd):
return check_password_hash(self.pwd, pwd) class Thing(db.Model):
__tablename__ = 'things'
# __table_args__ = {"useexisting": True} id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
title = db.Column(db.String(20), nullable=False)
text = db.Column(db.Text, nullable=False)
add_date = db.Column(db.DateTime, default=datetime.now) def __repr__(self):
return "<Todo %r>" % self.id

然后在 todolist\forms.py 中添加一个用于处理用户登陆的表单提交类,示例代码如下所示:

from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, TextAreaField, PasswordField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from models import User class RegisterForm(FlaskForm):
username = StringField('用户名:', validators=[
DataRequired(), Length(min=6, max=20)])
email = StringField('邮箱:', validators=[DataRequired(), Email()])
pwd = PasswordField('密码:', validators=[
DataRequired(), Length(min=8, max=120)])
confirm = PasswordField('确认密码:', validators=[
DataRequired(), EqualTo('pwd')])
submit = SubmitField('提交') def validate_username(self, username):
user = User.query.filter_by(name=username.data).first()
if user:
raise ValidationError("用户昵称已存在。") def validate_email(self, email):
user = User.query.filter_by(email=email.data).first()
if user:
raise ValidationError('邮箱已存在.') class LoginForm(FlaskForm):
username = StringField('用户名:', validators=[
DataRequired(), Length(min=6, max=20)])
password = PasswordField('密码:', validators=[DataRequired()])
submit = SubmitField('登陆') def validate_username(self, username):
user = User.query.filter_by(name=username.data)
if not user:
raise ValidationError('用户名不存在。')

然后修改我们的 todolist\app\views.py ,添加用户登陆和登出的路由处理函数,示例代码如下所示:

from flask import render_template, redirect, url_for, flash
from flask_login import login_user, login_required, current_user, logout_user
from app import app, db
from forms import RegisterForm, LoginForm
from models import User @app.context_processor
def inject_user():
user = User.query.first()
return dict(user=user) @app.route('/')
@app.route('/index')
def index():
if not current_user.is_authenticated:
return redirect(url_for('login'))
return render_template('index.html', title="首页") @app.route('/login', methods=['POST', 'GET'])
def login():
form = LoginForm()
if form.validate_on_submit():
name = form.username.data
pwd = form.password.data
user = User.query.filter_by(name=name).first()
if user and user.check_password_hash(pwd):
login_user(user)
flash('登陆成功。', category='info')
return redirect(url_for('index'))
else:
flash("密码或账户错误。", category='error')
return render_template('login.html', title='登录', form=form) @app.route('/logout')
@login_required
def logout():
logout_user()
flash('再见!')
return redirect(url_for('login')) @app.route('/register', methods=['POST', 'GET'])
def register():
form = RegisterForm()
if form.validate_on_submit():
username = form.username.data
email = form.email.data
pwd = form.pwd.data
user = User(name=username, email=email)
user.generate_password_hash(pwd)
db.session.add(user)
db.session.commit()
flash('注册成功', category='info')
return redirect(url_for('login'))
return render_template('register.html', title='注册', form=form)

接着,修改我们 todolist\app\templates\login.html 页面,添加用户登陆的表单,示例代码如下所示:

{% extends 'base.html' %} {% block content %}
<h1>登录页面</h1>
{% from 'bootstrap/form.html' import render_form %} {{ render_form(form) }}
{% endblock %}

修改我们的 todolist\app\templates\nav.html 页面,完善菜单栏的逻辑控制,示例代码如下所示:

<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="#">愿望清单</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button> <div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item {% if request.endpoint == 'index' %} active {% endif %}">
<a class="nav-link" href="{{ url_for('index') }}">首页<span class="sr-only">(current)</span></a>
</li>
</ul> <ul class="navbar-nav">
{% if current_user.is_authenticated and user %}
<li class="nav-item {% if request.endpoint == 'logout' %} active {% endif %}">
<a class="nav-link" href="{{ url_for('logout') }}">登出</a>
</li>
{% else %}
<li class="nav-item {% if request.endpoint == 'login' %} active {% endif %}">
<a class="nav-link" href="{{ url_for('login') }}">登录</a>
</li>
<li class="nav-item {% if request.endpoint == 'register' %} active {% endif %}">
<a class="nav-link" href="{{ url_for('register') }}">注册</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>

修改我们的 todolist\app\templates\index.html 页面,显示当前登陆的用户,示例代码如下所示:

{% extends 'base.html' %} {% block content %}

{% if current_user.is_authenticated and user %}
<h1>{{ current_user.name }},欢迎回来</h1>
{% else %}
<h1>首页</h1>
{% endif %} {% endblock %}

此时,当我们运行起我们的网站后进入注册页面 http://127.0.0.1:5000 就可以进行用户的注册、登陆和登出了。

参考连接

Flask 系列之 LoginManager的更多相关文章

  1. Flask 系列之 部署发布

    说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 通过 Windows 的 WSL,将我们的项目网站部署到 ...

  2. 【Python】Flask系列-URL和视图笔记

    1.学习目标 熟悉Flask相关知识. 熟悉web开发流程. 能独立开发Flask项目. 2.环境配置 Python虚拟环境安装 因为python的框架更新迭代太快了,有时候需要在电脑上存在一个框架的 ...

  3. Flask 系列之 优化项目结构

    说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 完善环境配置,添加 异常请求 处理 实现 400.404 ...

  4. Flask系列:数据库

    这个系列是学习<Flask Web开发:基于Python的Web应用开发实战>的部分笔记 对于用户提交的信息,包括 账号.文章 等,需要能够将这些数据保存下来 持久存储的三种方法: 文件: ...

  5. Flask 系列之 Migration

    说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 通过使用 flask-migrate 实现数据库的迁移操 ...

  6. Flask 系列之 Blueprint

    说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 学习如何使用 Blueprint 介绍 接触过 DotN ...

  7. Flask 系列之 Pagination

    说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 实现当前登录用户的事务浏览.添加.删除 操作 实现 首先 ...

  8. Flask 系列之 FlaskForm

    通过使用 FlaskForm ,可以方便快捷的实现表单处理. 说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验 ...

  9. Flask 系列之 Bootstrap-Flask

    说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 通过使用 Bootstrap-Flask 来进行页面美化 ...

随机推荐

  1. Dubbo 源码分析 - 服务引用

    1. 简介 在上一篇文章中,我详细的分析了服务导出的原理.本篇文章我们趁热打铁,继续分析服务引用的原理.在 Dubbo 中,我们可以通过两种方式引用远程服务.第一种是使用服务直联的方式引用服务,第二种 ...

  2. Java集合排序(面试必考点之一)

    集合是Java面试必考知识点,而集合的排序也是非常重要的,工作中经常用到,那么这个知识点也是必须要掌握的,下面是我曾经面试时被面试官问的问题: 根据API可知,Java集合的工具类Collection ...

  3. 技术干货:实时视频直播首屏耗时400ms内的优化实践

    本文由“逆流的鱼yuiop”原创分享于“何俊林”公众号,感谢作者的无私分享. 1.引言 直播行业的竞争越来越激烈,进过2018年这波洗牌后,已经度过了蛮荒暴力期,剩下的都是在不断追求体验.最近正好在做 ...

  4. 阿里技术分享:阿里自研金融级数据库OceanBase的艰辛成长之路

    本文原始内容由作者“阳振坤”整理发布于OceanBase技术公众号. 1.引言 OceanBase 是蚂蚁金服自研的分布式数据库,在其 9 年的发展历程里,从艰难上线到找不到业务场景濒临解散,最后在双 ...

  5. JavaScript使用浏览器内置XMLHttpRequest对象执行Ajax请求

    所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject).XMLHttpRequest 用于在后台与服务器交换数据.这意味着可以在不重新加载整个 ...

  6. Golang之发送消息至kafka

    windows下安装zookeeper 1.安装JAVA-JDK,从oracle下载最新的SDK安装(我用的是1.8的) 2.安装zookeeper3.3.6,下载地址:http://apache.f ...

  7. Asp.NetCoreWebApi图片上传接口(二)集成IdentityServer4授权访问(附源码)

    写在前面 本文地址:http://www.cnblogs.com/yilezhu/p/9315644.html 作者:yilezhu 上一篇关于Asp.Net Core Web Api图片上传的文章使 ...

  8. ionic2 基于ngx-translate实现多语言切换,翻译

    介绍 ngx-translate 是Angular 2+的国际化(i18n)库,在github的地址是箭头 https://github.com/ngx-translate/core 将ngx-tra ...

  9. 【python小工具】linux 低权限密码记录 提权小套路

    #!/usr/bin/python import os, sys, getpass, time current_time = time.strftime("%Y-%m-%d %H:%M&qu ...

  10. cookie、session总结

    前几天在调试第三方支付接口时碰到一个session失效问题,用了几天时间才搞明白,现在回想一下,主要还是由于cookie和session这一块的一些基本概念没有搞清楚,现总结一下. 浏览器使用HTTP ...