Flask 扫盲系列-数据库

简介: Flask 扫盲系列-数据库

在前面的学习中,我们已经简单搭建了一个在线股票走势查询系统,并且了解了 Flask 中的上下文,那么今天我们一起来学习下 Flask 中的数据库操作。

Flask-SQLAlchemy

说多数据库,相信大家都是再熟悉不过了,无论是什么程序,都需要和各种各样的数据打交道,那么保存这些数据的地方,就是数据库了。Flask 支持多种数据库,同时我们未来方便安全的操作数据库,这里选择使用 Flask-SQLAlchemy 插件来管理数据库的相关操作。

实战登陆

我们直接从实战出发,来实践下它们的用法。

在上一篇我们定义了一个登陆页面,但是对于登陆我们并没有校验,当然也没有保存任何用户信息,现在我们来完善登陆注册功能。

定义表结构

首先我们定义用户表的表结构,为了方便起见,我们使用插件 flask_login 来进行用户鉴权,在 app.py 文件中添加如下代码

from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin, login_user
import hashlib
db = SQLAlchemy(app)
# 用户表结构
class WebUser(UserMixin, db.Model):
    __tablename__ = 'webuser'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.String(64), unique=True, index=True)
    email = db.Column(db.String(64), unique=True, index=True)
    username = db.Column(db.String(64), unique=True, index=True)
    password_hash = db.Column(db.String(128))
    confirmed = db.Column(db.Boolean, default=False)
    def __init__(self, **kwargs):
        super(WebUser, self).__init__(**kwargs)
        if self.email is not None and self.avatar_hash is None:
            self.avatar_hash = hashlib.md5(
                self.email.lower().encode('utf-8')).hexdigest()
    @staticmethod
    def insert_user():
        users = {
            'user1': ['user1@luobo.com', 'test1', 1],
            'user2': ['user2@luobo.com', 'test2', 1],
            'admin1': ['admin1@luobo.com', 'admin1', 2],
            'admin2': ['admin2@luobo.com', 'admin2', 2]
        }
        for u in users:
            user = WebUser.query.filter_by(username=u[0]).first()
            if user is None:
                user = WebUser(user_id=time.time(), username=u, email=users[u][0],
                               confirmed=True, role_id=users[u][2])
                user.password = users[u][1]
                db.session.add(user)
            db.session.commit()
    @property
    def password(self):
        raise AttributeError('You can not read the password')
    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)
    def verify_password(self, password):
        if self.password_hash is not None:
            return check_password_hash(self.password_hash, password)

我们定义了用户表的字段,包括 user_id、emali、username 等,对于用户密码的存储,使用 security 工具进行哈希处理后存储。同时还定义了一个静态方法 insert_user 用于初始化用户。

修改视图函数

接下来我们修改 login 视图函数,进行真正的用户验证

@app.route('/login/', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = WebUser.query.filter_by(email=form.email.data).first()
        if user is not None and user.verify_password(form.password.data):
            login_user(user)
            flash('欢迎回来!')
            return redirect(request.args.get('next') or url_for('index'))
        flash('用户名或密码不正确!')
    return render_template('login.html', form=form)

数据库设置

下面我们还需要设置数据库连接信息

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + 'myweb.sqlite'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True

SQLALCHEMY_DATABASE_URI 是数据库的连接地址,我们直接使用轻巧的 sqlite 文件数据库,SQLALCHEMY_COMMIT_ON_TEARDOWN 设置为 True,表示每次请求结束后,都会自动提交数据库的变动。

下面我们在终端进入到 flask shell 中

C:\Work\code\Flask\flask_stock>flask shell

然后使用  Flask-SQLAlchemy 提供的函数 create_all() 创建数据库表

>>> from app import db
>>> db.create_all()

如果不出意外,此时当前目录下应该会生成一个 myweb.sqlite 文件。

之后我们在通过 WebUser 类的静态方法来插入初始用户

>>> from app import WebUser
>>> WebUser.insert_user()

此时如果我们通过数据库连接工具查看 webuser 表的话,会发现数据已经成功插入了。

配置 flask_login 插件

最后为了使用 flask_login 插件,我们还需要通过 LoginManager 对象来初始化 app 实例。LoginManager 对象的 session_protection 属性可以设为 None、'basic' 或 'strong',以提供不同的安全等级,防止用户会话遭篡改。

from flask_login import LoginManager
login_manager = LoginManager(app)
login_manager.session_protection = 'strong'

最后,Flask-Login 要求程序实现一个回调函数,使用指定的标识符加载用户。

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

现在我们就可以尝试使用已有的用户和密码去登陆系统了,如果不出意外的话,使用正确的用户名和密码才能成功登陆。

现在再把 flash 消息渲染到 HTML 页面上

{% for message in get_flashed_messages() %}
<div class="alert alert-warning">
     <button type="button" class="close" data-dismiss="alert">&times;</button>
     {{ message }}
 </div>
{% endfor %}

验证用户

下面我们再来看下如何验证用户是否登陆。

还记得我们的 WebUser 类其实是继承自 flask_login 的 UserMixin 类的,该类已经实现了如下的用户方法

属性/方法 说明
is_authenticated 如果用户已经认证,返回 True,否则返回 False
is_active 如果用户允许登陆,返回 True,否则返回 False
is_anonymous 如果当前用户未登录,返回 True,否则返回 False
get_id() 返回用户的唯一标识符,使用 Unicode 编码字符串

再结合 flask_login 提供的 current_user 对象,就可以判断用户的认证状态了。current_user 是一个和 current_app 类似的代理对象(Proxy), 表示当前用户。

修改 get_kline_chart 的 30 天逻辑

from flask_login import current_user
def get_kline_chart():
...
    if int(query_time) > 30:
        if current_user.is_authenticated:
            pass
        else:
            abort(403)
...

修改用户认证判断逻辑

因为在上一篇里我们在模板中是通过 {% if not auth %} 来判断用户登陆与否的,现在需要修改下

<ul class="nav navbar-nav navbar-right">
                {% if current_user.is_authenticated %}
                <li><a href="{{ url_for('logout') }}">Log Out</a></li>
                {% else %}
                <li><a href="{{ url_for('login') }}">Log In</a></li>
                {% endif %}
            </ul>

而对于 logout 视图函数,也做如下修改

from flask_login import logout_user, login_required
@app.route('/logout/')
@login_required
def logout():
    logout_user()
    return redirect(url_for('index'))

直接调用 logout_user 函数就可以登出用户,同时还需要注意,这里使用了 login_required 装饰器,顾名思义,只有认证了的用户才可以调用该装饰器装饰的视图函数,这样就保证了未登陆的用户无权限访问 /logout 地址。

实战注册

注册我们就不做的过于复杂了,只要用户输入正确的 email 地址且唯一并且两次 password 一致,我们就通过注册。

定义注册表单

创建一个注册表单类

class RegisterForm(FlaskForm):
    email = StringField('email', validators=[DataRequired()])
    password = PasswordField('password', validators=[DataRequired(),
                                                     EqualTo('confirm_pw', message='两次输入的密码需要一致!')])
    confirm_pw = PasswordField('confirm_pw', validators=[DataRequired()])
    submit = SubmitField('Submit')
    def validate_email(self, field):
        if WebUser.query.filter_by(email=field.data).first():
            raise ValidationError('该邮箱已经存在!')

以 validate_ 开头且后面跟着字段名的方法,是固定写法,用于自定义字段的验证方法。

然后我们再创建一个注册视图函数

@app.route('/register/', methods=['GET', 'POST'])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        email = form.email.data
        password = form.password.data
        user = WebUser.query.filter_by(email=email).first()
        if user is None:
            newuser = WebUser(email=email, username=email, password=password, user_id=time.time())
            db.session.add(newuser)
            flash("你可以登陆啦!")
            return redirect(url_for('login'))
        flash("邮箱已经存在!")
    return render_template('register.html', form=form)

在该视图函数中,我们接收表单传递过来的数据,并验证 email 是否存在,如果不存在则插入数据库。并且跳转至登陆页面。

最后我们再编写注册页面,创建 register.html 文件

{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}注册{% endblock %}
{% block page_content %}
{% for message in get_flashed_messages() %}
<div class="alert alert-warning">
     <button type="button" class="close" data-dismiss="alert">&times;</button>
     {{ message }}
 </div>
{% endfor %}
{{ wtf.quick_form(form) }}
{% endblock %}

这样,一个注册功能就完成了。

当然我们最好还是给出一个注册的入口,这个入口就在登陆表单的下面

<p>
    还没有用户?
    <a href="{{ url_for('register') }}">
        点击这里注册
    </a>
</p>

快来动手实践下吧!

相关文章
|
6月前
|
前端开发 关系型数据库 数据库
使用 Flask 连接数据库和用户登录功能进行数据库的CRUD
使用 Flask 连接数据库和用户登录功能进行数据库的CRUD
139 0
|
6月前
|
关系型数据库 API 数据库
盘点Flask与数据库的交互插件——Flask-Sqlalchemy
盘点Flask与数据库的交互插件——Flask-Sqlalchemy
100 0
|
2月前
|
JavaScript 前端开发 数据库
测试开发之路--Flask 之旅 (三):数据库
本文介绍了在 Flask 应用中实现权限管理的过程,包括使用 Flask-SQLAlchemy、Flask-MySQLdb、Flask-Security 和 Flask-Login 等扩展模块进行数据库配置与用户权限设置。首先创建数据库并定义用户、环境和角色模型,接着通过 Flask-Security 初始化用户和角色,并展示了如何便捷地管理权限。后续将深入探讨权限控制的具体应用。
74 4
测试开发之路--Flask 之旅 (三):数据库
|
3月前
|
数据采集 数据可视化 关系型数据库
【优秀python web设计】基于Python flask的猫眼电影可视化系统,可视化用echart,前端Layui,数据库用MySQL,包括爬虫
本文介绍了一个基于Python Flask框架、MySQL数据库和Layui前端框架的猫眼电影数据采集分析与可视化系统,该系统通过爬虫技术采集电影数据,利用数据分析库进行处理,并使用Echart进行数据的可视化展示,以提供全面、准确的电影市场分析结果。
132 4
|
3月前
|
数据采集 数据可视化 前端开发
基于python flask的旅游数据大屏实现,有爬虫有数据库
本文介绍了一个基于Python Flask框架开发的旅游数据大屏系统,该系统集成了爬虫技术、数据库存储和ECharts数据可视化,提供了一个全面、实时更新的旅游信息展示平台,旨在提升旅游行业用户体验和决策效率。
|
3月前
|
SQL 测试技术 数据库
Flask与SQLAlchemy的神秘力量:如何让你的数据库飞起来?
【8月更文挑战第31天】在现代Web开发中,Flask和SQLAlchemy是热门技术栈,前者是轻量级Web框架,后者为强大的ORM库。本文介绍如何在Flask项目中集成SQLAlchemy,通过示例展示数据库操作方法,并分享最佳实践,如熟悉ORM、编写测试及适度使用SQL语句,以提升开发效率和代码质量。
228 0
|
3月前
|
数据可视化 搜索推荐 数据挖掘
基于Python flask 的数据可视化平台,可定制,可连接数据库
本文介绍了一个基于Python Flask框架开发的可定制数据可视化平台,该平台支持多种数据库连接,并提供丰富的图表类型和个性化设置,以实现交互式数据分析和展示。
基于Python flask 的数据可视化平台,可定制,可连接数据库
|
5月前
|
API 数据库 数据库管理
Flask Web开发基础:数据库与ORM实战
该文介绍了如何使用 Flask、SQLAlchemy 和 SQLite 实现数据库操作。首先,通过创建虚拟环境和安装 flask-sqlalchemy(版本2.5.1)及 sqlalchemy(版本1.4.47)来设置环境。接着,配置数据库URI,定义User和Movie模型类表示数据库表,并通过db.create_all()创建表。文章还展示了如何插入、查询、更新和删除记录,强调了db.session.commit()在保存更改中的关键作用。查询涉及filter、order_by等方法,提供了一系列示例。
343 1
|
6月前
|
安全 数据库连接 数据库
Flask数据库操作实战:增删改查一网打尽
【4月更文挑战第15天】本文介绍了在Flask中进行数据库操作的方法,包括选择数据库扩展(如Flask-SQLAlchemy)、配置数据库、定义模型以及执行CRUD操作。通过Flask-SQLAlchemy的ORM功能,开发者可以方便地管理数据库表和记录。文章详细展示了如何创建模型、添加、查询、更新和删除数据,并提到了高级查询和关系映射。此外,还提及了数据库迁移工具Flask-Migrate以及性能优化和安全性问题。了解这些基础,有助于开发者构建高效、安全的Flask Web应用。
|
15天前
|
开发框架 前端开发 JavaScript
利用Python和Flask构建轻量级Web应用的实战指南
利用Python和Flask构建轻量级Web应用的实战指南
44 2
下一篇
无影云桌面