测试开发之路--Flask 之旅 (三):数据库

背景

通过前两次的努力,我们对环境有了增删查改以及部署和查看日志的能力。 现在已经处于将就可用的状态。但其实还差了很重要的东西,就是权限的管理。 因为不能说每个用户上来都能随便的重启和删除环境吧,太容易出事故了。所以我们想起码有最基本的隔离性。

Flask 扩展模块

上一次我们使用了 Flask-WTF 这个针对于表单的扩展模块。 这次为了加入权限管理,我们需要再安装以下这些扩展模块。

  • Flask-SQLAlchemy
  • Flask-MySQLdb
  • Flask-Security
  • Flask-Login

涉及到权限就需要有用户的概念,我们需要数据库来存储我们用户和环境的信息,所以要使用 Flask-SQLAlchemy 和 Flask-MySQLdb(我使用的是 mysql)。为了解决用户登录的问题引入 Flask-Login, 为了生成角色和权限的概念引入 Flask-Security。这里解释一下 Flask-Security,它无法单独使用,更像是 Flask-Login 和 Flask-SQLAlchemy 的扩展。 是为了增强他们的权限控制能力而存在的。所以再加入 Flask-Security 后,Flask-SQLAlchemy 和 Flask-Login 的使用方式都跟以前有些不太一样了。接下来我会一个一个介绍

创建数据库

我们先解决数据库的问题吧。 再安装好上面的所有模块后 (注:缺一不可),我们首先要在数据库中创建名叫 env 的库。供我们使用


再启动 app 前设置一下数据库参数:

# 连接mysql数据库的配置
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:root@172.27.1.221:3306/env'

然后我们创建一个 models.py

from __init__ import *
from flask_security import RoleMixin, UserMixin

# Create database connection object
db = SQLAlchemy(app)

# Define models
roles_users = db.Table('roles_users',
                       db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
                       db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))


class Role(db.Model, RoleMixin):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)
    description = db.Column(db.String(255))


class User(db.Model, UserMixin):

    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True)
    password = db.Column(db.String(255))
    active = db.Column(db.Boolean())
    confirmed_at = db.Column(db.DateTime())
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))
    envs = db.relationship('Env', backref=db.backref('user'))


class Env(db.Model):

    def __init__(self, name, user_id):
        self.name = name
        self.user_id = user_id

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), unique=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

看到这么一坨代码可能有点懵逼。我来解释解释吧。 Flask-SQLAlchemy 是一个 ORM 框架,它组织了数据库表到类的影射。所以我们可以使用管理这些类对象的方式管理数据库。 你看到上面我们创建了 User,Env 和 Role 类,分别对应了用户,环境和角色。它们都集成了 db.Model。我们把 SQLAlchemy(app) 赋值给 db,这是初始化我们数据库的方式。 然后你会发现 User 和 Role 又分别继承了 UserMixin 和 RoleMixin。暂时可以不用管它, 这个是 Flask-Security 的东西。 表之间的关系我用外键来定义,额,虽然我知道外键的性能不好。开发人员几乎从来不用。但是我这么个小玩意就不在意这些有的没的了,一共就没几条数据。看到上面对 roles_users 的定义可能大家会觉得有点懵逼。 这是 SQLAlchemy 处理多对多关系的方式:产生一张中间表。 SQLAlchemy 处理表关系的方式就是 relationship 方法。这部分内容有点多~~ 具体详细的 API 定义请大家参考官方文档:快速入门 — Flask-SQLAlchemy 2.0 documentation

接下来我们只需要调用下面的代码就会在数据库创建出这些表了。

db.create_all()

3 张表加一个 roles_users 的表。

数据库操作

现在我们有表了,我们想初始化一些数据。 所以我们先看看一些基础的操作。
例如我们想创建一个环境信息,我们可以这么做:

env = Env()
env.name = 'test01'
env.user_id = '1'
db.session.add(env)
db.session.commit()

这是添加一条数据的方式。 只要是增删改的操作,只要没有运行 db.session.commit(), 就不会真正的入库。 这是为了保证事务性。增加了一条数据后,现在我们来查询数据:

env = Env.query.filter_by(name='test01').first()

由于我们 model 的类都继承了 db.Models。 所以我们可以使用一些方法来进行查询。 也可以使用一些复杂一点的查询方式,如下:

Env.query.filter(name.endswith('01')).all()

使用 Flask-Security 创建 User 和 Role

OK,现在我们看看一开始没有说明的 UserMixin 和 RoleMixin。上面说过他们是 Flask-Security 针对 Flask-SQLAlchemy 做的扩展。通过 Flask-Security 我们可以很方便的管理用户权限但是它对我们的 model 有一定的要求。请看下图:


就是说我们一定要有 User 和 Role 这两张表以及包含相应的字段。 这样 Flask-Security 才能够帮助我们生成权限管理的解决方案。举个简单的例子,通过使用 Flask-Security, 我们可以用下面的方式创建用户:

from urls import db, User,  Role
from flask_security import SQLAlchemyUserDatastore, Security
# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
db.create_all()

admin = user_datastore.create_user(email='admin@4paradigm.com', password='admin')
# 生成普通用户角色和admin用户角色
user_datastore.create_role(name='User', description='Generic user role')
admin_role = user_datastore.create_role(name='Admin', description='Admin user role')
# 为admin添加Admin角色
user_datastore.add_role_to_user(admin, admin_role)
db.session.commit()

上面是我初始化数据库的代码。 为了能使用 Flask-Security。我们使用 SQLAlchemyUserDatastore 来封装 db, 使用 Security 封装我们的 web app。 接下来就可以看到我们使用很方便的方式创建 user 和 role。 并且使用 add_role_to_user 的方式为一个用户添加角色。Flask-Security 为我们提供了很多有用的方法。请看下面的截图:

更多的 API 请查看官方文档:API — Flask-Security 3.0.0 documentation

未完待续

上面说的这些方法都可以很有效的管理我们数据库中 User 和 Role 的关系。再下一篇帖子中,我会详细介绍如何使用 Flask-Security 来做权限控制。今天太晚了~ 先这样吧

另外欢迎大家加入我的知识星球, 最近正在更新手把手教你人工智能测试系列。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/359012.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

我在代码随想录|写代码Day20之二叉树-700. 二叉搜索树中的搜索,98. 验证二叉搜索树,530.二叉搜索树的最小绝对差

学习目标: 博主介绍: 27dCnc 专题 : 数据结构帮助小白快速入门 👍👍👍👍👍👍👍👍👍👍👍👍 ☆*: .。. o(≧▽≦)…

研发人员如何做好日常工作的稳定性保障

一、前言 二、稳定性介绍 三、实际操作流程 1、需求分析阶段 2、设计阶段 2、1备选架构 2、2方案设计 2、3 架构设计 2、4设计的checklist 2、5的checklist 3、开发联调 4、自测环节 5、上线前环节 6、上线后的验收和复盘 四、稳定性、效率、成本之间的考量 五、…

教你一招轻松把模糊的照片变高清

亲爱的朋友们,你们是否也曾经遇到过这样的问题——精心拍摄的照片或珍藏已久的图片突然变得模糊不清,让人心情郁闷?别担心,我发现了解决这个问题的秘诀!借助一些专业的图片修复工具,那些模糊的瞬间可以重新…

第 8 章:Linux中使用时钟、计时器和信号

在本章中,我们将开始探索Linux环境中可用的各种计时器。随后,我们将深入了解时钟的重要性,并探讨UNIX时间的概念。接下来,我们将揭示在Linux中使用POSIX准确测量时间间隔的方法。之后,我们将进入std::chrono的领域&…

05 SB3之Spring Initializr+运行方式+自动配置原理(TBD)

1. 使用IDEA内置Spring Initializr 生成SB项目 最上方Server URL可以选择借助哪个平台生成, 可选阿里云 作为对比 , 官方可选版本最旧为3.1.18 ; 阿里云可选最新版本为3.0.2 本次选择3.1.8版本, 并且添加Spring Web依赖(包括RESTful / Spring MVC/)和Lombok依赖 生成后端项目…

1 月 29日算法练习-二分法

二分法是一种高效的查找方法,它通过将问题的搜索范围一分为二(两边具有明显的区别),迭代地缩小搜索范围,直到找到目标或确定目标不存在。 二分法适用于有序数据集合,并且每次迭代可以将搜索范围缩小一半。 …

【GAMES101】Lecture 12 阴影 Shadow Mapping

这里是光栅化的最后一部分,讲这个光栅化里面怎么实现这个阴影 实际上阴影就是光源看不到的地方但是是我们能看到的地方,那这个地方就应该有阴影,那具体怎么做呢,这个就叫做Shadow Mapping,分两步做 我们之前说过这个解…

初识attention

近年来,attention机制在机器视觉和机器翻译领域受到了广泛的关注,有很多文章都是融合attention来提高性能。attention受启发于人类的视觉系统,最先应用于序列化的机器翻译(NLP)后又推广到计算机视觉中,本篇文章就来简单学习一下at…

[GN] 设计模式——面向对象设计原则概述

文章目录 面向对象设计原则概述单一职责原则开闭原则里氏代换原则依赖倒转原则接口隔离原则合成复用原则迪米特法则 总结 提示:以下是本篇文章正文内容,下面案例可供参考 面向对象设计原则概述 单一职责原则 一个类只负责一个功能领域中的相应职责 类…

JavaScript DOM属性和方法之attribute属性对象

在HTML的DOM中,attribute对象表示HTML属性。HTML属性始终属于HTML元素,它在DOM节点中被称为属性节点。在DOM中,NamedNodeMap对象表示元素属性节点的无序集合,我们可以通过指定的索引访问指定的属性。通过element对象的attribute属…

【Leetcode】两数之和

目录 题目: 解法1:暴力双for 1.想到的第一种方法两for循环解 复杂度分析 解法2:hash表 总结: 笔记: 题目: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标…

实现扫码登录

扫码登录是如何实现的? 二维码信息里主要包括唯一的二维码ID,过期的时间,还有扫描状态:未扫描、已扫描、已失效。 扫码登录流程 用户打开网站登录页面的时候,浏览器会向二维码服务器发送一个获取登录二维码的请求。二维码服务器收…

让Elasticsearch飞起来!百亿级实时查询优化实战

让Elasticsearch飞起来!百亿级实时查询优化实战 - 简书 最近的一个项目是风控过程数据实时统计分析和聚合的一个 OLAP 分析监控平台,日流量峰值在 10 到 12 亿上下,每年数据约 4000 亿条,占用空间大概 200T。 面对这样一个数据量…

【Java】内存溢出和内存泄露的区别

目录 概念 内存溢出分类 内存泄漏分类 发生场景以及解决方法 内存溢出 内存泄漏 解决方法 这道题是面试常考的,一定要区分好区别,我之前就是直接认为内存溢出就是内存泄漏了 概念 内存溢出:是指程序在申请内存时,没有足够…

国考省考行测:分析推理,形式逻辑,集合推理,真假推理

国考省考行测:分析推理,形式逻辑 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能,附带行测和申论,而常规国考省考最重要的还是申论和行测,所以大家认真准备吧,我讲一起屡屡申论和…

基于Springboot的视频网站系统的设计与实现(有报告)。Javaee项目,springboot项目。

演示视频: 基于Springboot的视频网站系统的设计与实现(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层…

git diff查看比对两次不同时间点提交的异同

git diff查看比对两次不同时间点提交的异同 用 git diff命令: git diff commit-id-1 commit-id-2 不同commit-id在不同的时间点提交产生,因为也可以认为git diff是比对两个不同时间点的代码异同。 git diff比较不同commit版本的代码文件异同_git diff c…

顺序表的奥秘:高效数据存储与检索

🍿顺序表 🧀1、顺序表的实现🍥1.1 创建顺序表类🍥1.2 插入操作🍥1.3 查找操作🍥1.4 删除操作🍥1.5 清空操作 🧀2、ArrayList的说明🧀3、ArrayList使用🍥3.1 A…

Focaler-IoU:更聚焦的IoU损失

摘要 边界框回归在目标检测领域中起着至关重要的作用,而目标检测的定位精度在很大程度上取决于边界框回归的损失函数。现有的研究通过利用边界框之间的几何关系来提高回归性能,而忽略了难易样本分布对边界框回归的影响。本文分析了难易样本分布对回归结…

在linux上进行编译调试

1.相关疑问 1. 为什么在代码里使用了一个未定义过的函数(如add()),在编译阶段不会报错,在链接阶段会报错呢? 答:先说几个代码编译的结论: 单个\.c源文件文件被编译成机器码文件时&#xff0c…