当前位置: 首页 > news >正文

使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(三)——使用Flask-Login库实现登录功能...

使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用

使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化

使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(三)——使用Flask-Login库实现登录功能

使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(四)——对 run.py 的调整

使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(五)——实现注册功能

 

本次示例的源码下载:点击下载

Flask-Login 库的中文文档:点击进入

Flask-Login 库的新版英文文档:点击进入

使用 WTForms 进行表单验证:点击进入

 

一、导入并初始化 Flask-Login 库

在项目根目录下的/demo/__init__.py 文件的头部,import 进 flask_login 库

from flask_login import LoginManager

在 create_app 函数的前面加入初始化操作:

"""
初始化登录管理器
"""
login_manager = LoginManager()

"""
这里的参数格式是:蓝图名称.函数名
这里是指定了当用户未登录的时候,进入需要登录才能进入的页面时,会自动跳转到的页面。
"""
login_manager.login_view = "user.login"

在 create_app 函数中的 app = Flask(__name__) 下面加入:

login_manager.init_app(app)

完整的代码是:

二、实现登录模块

 1.增加 MD5 加密公共函数

在该路径下创建文件并编写以下代码:

/demo/common/encrypt.py

def md5(text):
    import hashlib
    m = hashlib.md5()
    t = text.encode(encoding="utf-8")
    m.update(t)
    return m.hexdigest()

2.创建用户模块

①创建以下目录

/demo/modules/users

/demo/modules/users/forms

/demo/modules/users/models

/demo/modules/users/templates

②创建 /demo/modules/users/views.py

3.使用 Flask-WTF 库来验证提交的表单,点击查看文档

 在 forms 目录下 创建 users.py 文件,做登录表单验证

/demo/modules/users/forms/users.py

# config=utf-8
from flask_wtf import Form
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, Length, Email


class LoginForm(Form):
    accountNumber = StringField('accountNumber', validators=[DataRequired('账号不可以是空的'),
                                                             Length(-1, 200, '账号的字符数不可以超过 200 个'),
                                                             Email('账号只能是邮箱')])
    password = PasswordField('password', validators=[DataRequired('密码不可以是空的'),
                                                     Length(6, 20, '密码的字符数只能在 6 - 20 个之间')])

 

 

4.创建操作数据库类

/demo/modules/users/models/users.py

# config=utf-8
from flask_login import UserMixin
from demo.common import db


class User(db.Model, UserMixin):
    """
    用户实体信息
    Attributes:
        id:用户编号。
        accountNumber:账号。
        password:密码。
        name:用户昵称。
    """
    id = db.Column(db.Integer, primary_key=True)
    accountNumber = db.Column(db.String(200), unique=True)
    password = db.Column(db.String(50), unique=True)
    name = db.Column(db.String(20), unique=True)

    __tablename__ = 'py_user'

    def __init__(self, user_id=None, account_number=None, password=None, name="anonymous"):
        """
        初始化用户信息。
        Args:
            user_id (int): 用户编号
            account_number(string):账号
            password(string):密码
            name (string):昵称
        """
        self.id = user_id
        self.accountNumber = account_number
        self.password = password
        self.name = name

db.Model 类是数据库操作类,实现了数据库的功能。

UserMixin 是 flask-login 库提供的一个用户的基类,定义了 flask-login 的登录用户必需使用到的属性和方法等。

5.在 views.py 中实现具体的登录功能。

/demo/modules/users/views.py 的完整代码

# config=utf-8
from flask import Blueprint, request, redirect, url_for
from flask import render_template
from flask_login import login_user, logout_user
from demo import login_manager
from demo.common.encrypt import md5
from demo.modules.users.models.users import User
from demo.modules.users.forms.users import LoginForm

userRoute = Blueprint('user', __name__, url_prefix='/user', template_folder='templates', static_folder='static')


@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))


@userRoute.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()

    if request.method == 'POST':
        if not form.validate_on_submit():
            return render_template('login.html', form=form)

        user = User.query.filter(User.accountNumber == form.accountNumber.data,
                                 User.password == md5(form.password.data)).first()

        if user:
            login_user(user)
            return redirect("/")

    return render_template('login.html', form=form)


@userRoute.route('/logout')
def logout():
    logout_user()
    return redirect(url_for('.login'))

其中,要以 @login_manager.user_loader 来描述一个函数,表示 flask-login 库在获取当前已登录的用户信息时,会该用该函数来获取:

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

 

 

6.注册用户模块,在 /run.py 文件里增加:

from demo.modules.home.views import homeRoute
from demo.modules.users.views import userRoute

DEFAULT_MODULES = [homeRoute,
                   userRoute]

/run.py 完整代码:

# config=utf-8
from demo import create_app
from demo.modules.home.views import homeRoute
from demo.modules.users.views import userRoute

DEFAULT_MODULES = [homeRoute,
                   userRoute]

app = create_app('config.py')

for module in DEFAULT_MODULES:
    app.register_blueprint(module)


@app.before_request
def before_request():
    """
    这里是全局的方法,在请求开始之前调用。
    其中 flask 有个全局的变量 g,它是和 session 一样的用途,可以使用它来保存当前用户的数据
    Returns:

    """
    pass


if __name__ == '__main__':
    app.run()

 

7.创建模板页面

①创建以下目录:

/demo/static

/demo/static/js

/demo/static/css

/demo/static/img

分别用于保存 JS、CSS 和图片。

页面调用的静态文件的目录是应用目录下的 static 目录,如果将这些文件放到其它目录中 ,则无法在页面中引用。

 ②下载 jquery 并保存在/static/js/jquery/目录下

/static/js/jquery/jquery-2.2.0.min.js

③在 /demo/templates/base.html 中引入 jquery:

<!DOCTYPE html>
<html lang="cn">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
    <script src="/static/js/jquery/jquery-2.2.0.min.js"></script>
    {% block head %}{% endblock %}
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>

④在 /demo/modules/users/templates 目录创建 login.html 页面:

{% extends "base.html" %}
{% block title %}python flask user page{% endblock %}
{% block head %}
    <style type="text/css"></style>
{% endblock %}
{% block content %}
    <form action="{{ url_for('user.login') }}" method="post">
        {% if form.errors %}
            <ul>
                {% for name, errors in form.errors.items() %}
                    {% for error in errors %}
                        <li>{{ error }}</li>
                    {% endfor %}
                {% endfor %}
            </ul>
        {% endif %}
        账号:{{ form.accountNumber(size=20) }}<label>{{ form.accountNumber.errors[0] }}</label><br/>
        密码:<input name="password" type="password"/><br/>
        {{ form.hidden_tag() }}
        <button type="submit">登录</button>
    </form>
    <a href="/">返回</a>
{% endblock %}

其中这段表示遍历输出所有表单错误信息。

        {% if form.errors %}
            <ul>
                {% for name, errors in form.errors.items() %}
                    {% for error in errors %}
                        <li>{{ error }}</li>
                    {% endfor %}
                {% endfor %}
            </ul>
        {% endif %}

 

完成了,这几章只是对在 Flask 使用中的一种补充和记录,具体还是查文档。

 

转载于:https://www.cnblogs.com/cjnmy36723/p/5212047.html

相关文章:

  • 开发基于SpringBoot和BootStrap的全栈论坛网站(二):后端人员如何快速使用BootStrap
  • java虚拟机(三)java的垃圾回收机制详解
  • 查看ORACLE的实际执行计划
  • 开发基于SpringBoot和BootStrap的全栈论坛网站(三):登陆注册以及cookies的功能完成
  • 开发基于SpringBoot和BootStrap的全栈论坛网站(四):完成问题发布功能
  • OSChina 周日乱弹 ——冯小牛 我要治愈你!
  • 开发基于SpringBoot和BootStrap的全栈论坛网站(五):完成首页展示以及分页功能
  • 冒泡排序法与二分查找法
  • github回退版本时本地代码被覆盖(已解决)
  • CentOS 6.5系统上安装SVN服务器端的方法及目录访问权限配置(转总结)
  • 开发基于SpringBoot和BootStrap的全栈论坛网站(六):完成个人中心、问题详情和问题编辑
  • 开发基于SpringBoot和BootStrap的全栈论坛网站(七):完成回复和二级回复功能
  • 项目管理过程 工作绩效数据,信息和报告
  • 开发基于SpringBoot和BootStrap的全栈论坛网站(八):完成回复通知的功能
  • 架构师
  • #Java异常处理
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • Akka系列(七):Actor持久化之Akka persistence
  • css系列之关于字体的事
  • echarts花样作死的坑
  • HomeBrew常规使用教程
  • Intervention/image 图片处理扩展包的安装和使用
  • JWT究竟是什么呢?
  • Kibana配置logstash,报表一体化
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • PHP 小技巧
  • Transformer-XL: Unleashing the Potential of Attention Models
  • Vim 折腾记
  • Vue2.x学习三:事件处理生命周期钩子
  • 动态规划入门(以爬楼梯为例)
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 关于for循环的简单归纳
  • 跨域
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 延迟脚本的方式
  • 以太坊客户端Geth命令参数详解
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • #大学#套接字
  • (12)目标检测_SSD基于pytorch搭建代码
  • (Python) SOAP Web Service (HTTP POST)
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (转)ObjectiveC 深浅拷贝学习
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • .NET 设计模式初探
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .net程序集学习心得
  • .NET上SQLite的连接
  • /3GB和/USERVA开关
  • @ConditionalOnProperty注解使用说明
  • [ C++ ] 继承
  • []error LNK2001: unresolved external symbol _m
  • []利用定点式具实现:文件读取,完成不同进制之间的