Flask Web开发:数据库

目录

在虚拟环境中安装Flask-SQLAlchemy:

一、配置

 数据库配置示例:

二、定义模型

Role 和 User 模型代码: 

(1)常用的 SQLAlchemy 列类型:​编辑

(2)常用的 SQLAlchemy 列选项:

三、关系

在数据库模型中定义关系补充如下:

常用的 SQLAlchemy 关系选项:​编辑

除了一对多关系之外:

四、数据库操作

(1)设置FLASK_APP 环境变量

 (2)虚拟环境终端中使用 flask shell 命令启动

4.1 创建表

4.2 插入行

(1)创建一些角色和用户如下:

(2)对数据库的改动通过数据库会话(也称事务)管理,由 db.session 表示。准备把对象写入数据库之前,要先将其添加到会话中:

 (3)然后我们调用 commit() 方法提交会话,这样对象才被真正写入了数据库。

(4)数据库会话(事务)可以保证数据库的一致性。

  (5)要查看data.sqlite。

4.3 修改行

4.4 删除行

4.5 查询行

(1)Flask-SQLAlchemy 为每个模型类都提供了 query 对象。最基本的模型查询是使用 all() 方法取回对应表中所有记录:

 如果退出了当前 shell,再重新打开的。

(2)常用的 SQLAlchemy 查询过滤器:


这里我们使用 Flask-SQLAlchemy 扩展来进行数据库操作,SQLAlchemy 是一个强大的关系型数据库框架,支持多种数据库后台。SQLAlchemy 提供了高层 ORM,也提供了使用数据库原生 SQL 的低层功能。

在虚拟环境中安装Flask-SQLAlchemy

pip install flask-sqlalchemy

一、配置

在 Flask-SQLAlchemy 中,数据库使用 URL 指定,如下:

数据库引擎    URL
MySQL    mysql://username:password@hostname/database
Postgres    postgresql://username:password@hostname/database
SQLite(Linux,macOS)    sqlite:absolute/path/to/database
SQLite(Windows)    sqlite:///c:/absolute/path/to/databasehostname:数据库服务所在的主机
database:要使用的数据库名
username:数据库用户名
password:数据库密码

注意:

SQLite 数据库没有服务器,因此不用指定 hostname、username 和 password。URL 中的 database 是磁盘中的文件名。
使用的数据库URL必须保存到 Flask 配置对象的 SQLALCHEMY_DATABASE_URI 键中。
建议把 SQLALCHEMY_TRACK_MODIFICATIONS 键设为 False,以便在不需要跟踪对象变化时降低内存消耗。

 数据库配置示例:

import os
from flask_sqlalchemy import SQLAlchemy

# 定义SQLite绝对路径
basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + \
    os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app) # 实例化SQLAlchemy

二、定义模型


在 ORM(对象关系映射器)中,模型一般是一个 Python 类,类中的属性对应于数据库表中的列。Flask-SQLAlchemy 实例为模型提供了一个基类以及一系列辅助类和辅助函数,可用于定义模型的结构。

如下实体 – 关系图中的 roles 表和 users 表,我们可以分别定义为 Role 和 User 模型:

Role 和 User 模型代码: 

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)

    def __repr__(self):
        return '<Role %r>' % self.name


class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)

    def __repr__(self):
        return '<User %r>' % self.username

类变量 __tablename__ 定义在数据库中使用的表名,如不定义,则会使用默认的表名。
db.Column 类构造函数的第一个参数是数据库列和模型的类型,其他参数则是一些列选项,如主键(primary_key)、索引(index)、不允许重复(unique)等。
__repr()__ 方法返回一个具有可读性的字符串表示模型,不是强制要求,可方便调试和测试。


(1)常用的 SQLAlchemy 列类型:

(2)常用的 SQLAlchemy 列选项:

三、关系

关系型数据库使用关系把不同表中的行联系起来,上面那个关系图中表示的实际上是一种一对多关系,即一个角色可属于多个用户,而每个用户只能由一个角色。

在数据库模型中定义关系补充如下:

class Role(db.Model):
	# ...
	users = db.relationship('User', backref='role')

class User(db.Model):
	# ...
	role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

也就是

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    users = db.relationship('User', backref='role')

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

         将 User 模型中的 role_id 列定义为外键,来联接这两个表。传给 db.ForeignKey() 的参数 roles.id 声明,这列的值是 roles 表中相应行的 id值。


        添加到 Role 模型中的 users 属性,代表整个关系的面向对象视角,对于一个 Role 类的实例,其 users 属性将返回与角色相关联的用户组成的列表。


         db.relationship() 的第一个参数编码整个关系的另一端是哪个模型;backref 参数向 User 模型中添加一个 role 属性,从而定义反向关系。通过 User 实例的这个role属性可以获取对应的 Role 模型的对象数情况下,db.relationship() 都能自行找到关系中的外键,但有时却无法确定哪一列是外键。

         例如,如果 User 模型中有两个或以上的列定义为 Role 模型的外键,SQLAlchemy 就不知道该使用哪一列。如果无法确定外键,就要为 db.relationship() 提供额外的参数。

常用的 SQLAlchemy 关系选项:

除了一对多关系之外:

一对一 关系可以用一对多关系表示,但调用 db.relationship() 时要把 uselist 设为 False ,把“多”变成“一”。
多对一 关系也可使用一对多表示,对调两个表即可,或者把外键和 db.relationship() 都放在“多”这一侧。
最复杂的关系类型是多对多 ,需要用到第三张表,这个表称为关联表(或联结表 )。

四、数据库操作


为了方便学习,我们先再Python shell中实际操作数据库模型,先设置 FLASK_APP 环境变量,然后再虚拟环境终端中使用 flask shell 命令启动。

(1)设置FLASK_APP 环境变量

先看要运行的.py文件是哪个目录下

根据图片可知,路径 D:\webflask\shiyan5\示例5-1\hello5-1.py, Flask 应用程序文件名为 hello5-1.py

在运行 flask shell 命令之前,请确保已经正确设置了环境变量 FLASK_APP,并且值为应用程序文件的完整路径。在 Windows 环境下,可以使用以下命令设置环境变量:

set FLASK_APP=D:\webflask\shiyan5\示例5-1\helloa1.py

 (2)虚拟环境终端中使用 flask shell 命令启动

flask shell

4.1 创建表

首先要让 Flask-SQLAlchemy 根据模型类创建数据库。 db.create_all() 函数将寻找所有 db.Model 的子类,然后再数据库中创建对应的表:

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

执行完上面命令后,在应用目录中就会产生一个 data.sqlite文件。

如果数据库表已经存在于数据库中,那么 db.create_all() 不会重新创建或者更新相应的表。使用 db.drop_all() 可以删除旧表,然后再重新创建,这样可以更新数据库,但是并不推荐,因为会丢失原有的数据。

 更新现有数据库表的粗暴方式是先删除旧表再重新创建:

>>> db.drop_all()
>>> db.create_all()

4.2 插入行

(1)创建一些角色和用户如下:

>>> from helloa1 import Role, User
>>> admin_role = Role(name='Admin')
>>> mod_role = Role(name='Moderator')
>>> user_role = Role(name='User')
>>> user_john = User(username='john', role=admin_role)
>>> user_susan = User(username='susan', role=user_role)
>>> user_david = User(username='david', role=user_role)

1.模型的构造函数接受的参数是使用关键字参数指定的模型属性初始值。
2.role 属性也可使用,虽然它不是真正的数据库列,但却是一对多关系的高级表示。
3.id 属性为主键,通常有数据库自身管理。而现在这些对象只存在于 Python 中,还未写入数据库,因此 id 并未赋值。


(2)对数据库的改动通过数据库会话(也称事务)管理,由 db.session 表示。准备把对象写入数据库之前,要先将其添加到会话中:

>>> db.session.add(admin_role) 
>>> db.session.add(mod_role) 
>>> db.session.add(user_role) 
>>> db.session.add(user_john) 
>>> db.session.add(user_susan) 
>>> db.session.add(user_david)

也可以简写成

>>> db.session.add_all([admin_role, mod_role, user_role, user_john, user_susan, user_david])

 (3)然后我们调用 commit() 方法提交会话,这样对象才被真正写入了数据库。

>>> db.session.commit()

(4)数据库会话(事务)可以保证数据库的一致性。

         提交操作使用原子方式把会话中的对象全部写入数据库。如果在写入会话的过程中发生了错误,那么整个会话都会失效。如果你始终把相关改动放在会话中提交,就能避免因部分更新导致的数据库不一致。

数据库会话也可以调用 db.session.rollback() 进行回滚,回滚后添加到数据库会话中的所有对象都将还原到它们在数据库中的状态。

  (5)要查看data.sqlite。

位于 D:\webflask\shiyan5\示例5-1\data.sqlite 路径下的 SQLite 数据库中的表,请按照以下步骤操作:

  1. 打开 SQLite 命令行工具。你可以在终端中输入以下命令:

    sqlite3 D:\webflask\shiyan5\示例5-1\data.sqlite
  2. 在 SQLite 命令行工具中,输入 .tables 命令。这将显示出当前数据库中的所有表格名称。

    .tables
  3. 如果你想查看某个特定表格中的数据,请使用 SELECT 查询语句。例如,如果你想查看名为 users 的表格中的所有数据,请输入以下命令:

    SELECT * FROM users;

    这将返回 users 表格中的所有数据。

  4. 请注意,表格名称必须以小写字母输入,否则可能会找不到表格。另外,建议在表格名称后面添加分号(;)来结束查询语句,这样可以确保命令被正确解释。

4.3 修改行

在数据库会话上调用 add() 方法也可以更新模型,如将 Admin 角色重命名未 Administrator

>>> admin_role.name = 'Administrator'
>>> db.session.add(admin_role) 
>>> db.session.commit()
>>>> admin_role.name       
'Administrator'

 

4.4 删除行

数据库会话可以用 delete() 方法来删除数据,如将 Moderator 角色从数据库中删除:

>>> db.session.delete(mod_role)
>>> db.session.commit()

 

删除与插入和更新一样,只有提交数据库会话后才会执行。

4.5 查询行

(1)Flask-SQLAlchemy 为每个模型类都提供了 query 对象。最基本的模型查询是使用 all() 方法取回对应表中所有记录:
>>> Role.query.all()
[<Role 'Administrator'>, <Role 'User'>]
>>> 
>>> User.query.all()
[<User 'john'>, <User 'susan'>, <User 'david'>]

使用过滤器可以配置 query 对象来进行更精准的数据库查询,如查找角色为 “User” 的所有用户

>>> User.query.filter_by(role=user_role).all()
[<User 'susan'>, <User 'david'>]

 若想查看 SQLAlchemy 为查询生成的原生SQL语句,可以将 query 对象转换为字符串:

>>> str(User.query.filter_by(role=user_role))
'SELECT users.id AS users_id, users.username AS users_username, users.role_id AS users_role_id \nFROM users \nWHERE ? = users.role_id'

 如果退出了当前 shell,再重新打开的。

前面例子创建的对象就不会以 Python 对象的方式存在,只能从数据库表中进行读取,重新创建Python对象。如下例发起一个查询,加载名为“User” 的用户角色:

user_role = Role.query.filter_by(name='User').first()
  • first() 方法只返回第一个结果,如果没有结果的化,返回None。
  • all() 方法以列表的形式返回查询到的所有结果。
(2)常用的 SQLAlchemy 查询过滤器:

(3)常用的 SQLAlchemy 查询执行方法:

 (4)关系与查询的处理方式类似,下面的例子首先查询角色为 User 的用户有哪些,然后又查询了用户susan的角色是什么,分别从关系的两端查询角色和用户之间的一对多关系。

>>> users = user_role.users
>>> users
[<User 'susan'>, <User 'david'>]
>>> users[0].role
<Role 'User'>

 可以发现这里再执行 user_role.users时,隐式的调用了 all()方法,此时 query 对象被隐藏了,这样就无法再使用过滤器进行更精准的查询(如将结果按字母顺序排序)。

要想解决这个问题,我们需要在 Role 类的 db.relationship() 方法中加入 lazy='dynamic' 参数的设置,从而禁止自动执行查询。

示例5-4:helloa1.py:动态数据库关系

class Role(db.Model):
	# ...
	users = db.relationship('User', backref='role', lazy='dynamic')
	# ...

原来的

 加了之后

 这样配置关系之后,user_role.users 将返回一个尚未执行的查询,因此可以在其上添加过滤器:

>>> user_role.users.order_by(User.username).all()
[<User 'david'>, <User 'susan'>]
>>> user_role.users.count()
2

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

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

相关文章

基于springboot实现冬奥会科普平台系统【项目源码+论文说明】计算机毕业设计

基于SpringBoot实现冬奥会科普平台系统演示 摘要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理平台应运而生&…

vue3-响应式核心

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue3-响应式核心 响应式核心 目录 响应式核心 3.1ref() 3.2computed () 3.3 reactive() 3.4 …

ESP32 MicroPython AI摄像头应用⑩

ESP32 MicroPython AI摄像头应用⑩ 1、AI摄像头应用2、移动检测&#xff08;LCD显示&#xff09;3、实验内容3、参考代码4、实验结果 1、AI摄像头应用 我们小车MCU支持AI(人工智能)加速&#xff0c;可以用于加速神经网络计算和信号处理等工作的向量指令 (vector instructions)…

一文讲明 网络调试助手的基本使用 NetAssist

我 | 在这里 &#x1f575;️ 读书 | 长沙 ⭐软件工程 ⭐ 本科 &#x1f3e0; 工作 | 广州 ⭐ Java 全栈开发&#xff08;软件工程师&#xff09; &#x1f383; 爱好 | 研究技术、旅游、阅读、运动、喜欢流行歌曲 &#x1f3f7;️ 标签 | 男 自律狂人 目标明确 责任心强 ✈️公…

全球地表水年度数据集JRC Yearly Water Classification History, v1.4数据集

简介&#xff1a; JRC Yearly Water Classification History, v1.4是一个对全球水资源进行分类的数据集&#xff0c;覆盖了1984年至2019年的时间范围。该数据集是由欧盟联合研究中心&#xff08;JRC&#xff09;开发的&#xff0c;使用的数据源是来自Landsat系列卫星的高分辨率…

澳洲猫罐头如何?我亲自喂养过的优质猫罐头分享

猫罐头要符合三点&#xff1a;营养配方完整均衡、原料新鲜优质、生产工艺科学可靠。只有具备这些特点&#xff0c;才是品质上乘的猫罐头。 猫罐头的三个要素&#xff0c;一个都不能少。配方不均衡&#xff0c;营养就不足&#xff1b;原料不新鲜&#xff0c;生产出来的猫罐头就…

NX二次开发UF_CAM_ask_tool_matl_db_object 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;里海NX二次开发3000例专栏 UF_CAM_ask_tool_matl_db_object Defined in: uf_cam.h int UF_CAM_ask_tool_matl_db_object(UF_CAM_db_object_t * db_obj ) overview 概述 This function provides the database object which is…

NameServer源码解析

1 模块入口代码的功能 本节介绍入口代码的功能&#xff0c;阅读源码的时候&#xff0c;很多人喜欢根据执行逻辑&#xff0c;先从入口代码看起。NameServer部分入口代码主要完成命令行参数解析&#xff0c;初始化Controller的功能。 1.1 入口函数 首先看一下NameServer的源码目…

长期暴露于空气污染与精神障碍存在因果关系 |UK Biobank周报(11.2)

郑老师统计课程&#xff0c;欢迎点击报名&#xff1a;Nhanes公共数据库挖掘 课程 英国生物银行&#xff08;UK Biobank&#xff0c;UKB&#xff09;是英国迄今以来规模最大的有关致病或预防疾病的基因和环境因子的信息资源库。目的是探求一些特定基因、生活方式和健康状况之间的…

BUUCTF [BJDCTF2020]鸡你太美 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。来源&#xff1a; https://github.com/BjdsecCA/BJDCTF2020 密文&#xff1a; 下载附件&#xff0c;解压得到两个.gif图片。 第一个gif图片&#xff1a; 第二个gif图片无法打开。…

ROS navigation栅格地图原点位置如何确定?

背景 利用ros进行导航时&#xff0c;生成一张栅格地图&#xff0c;包含gridMap.pgm和gridMap.yaml。现在想要将栅格地图及轨迹在其他应用上显示&#xff0c;需要确定地图的坐标系原点。 gridMap.yaml格式 image: gridMap.pgm  #文件名 resolution: 0.20000  #地图分辨率 …

第十五章---I/O(输入/输出)

15.1输入输出流 流是一组有序的数据序列&#xff0c;根据操作的类型&#xff0c;可分为输入流和输出流两种。I/O(Input/Output,(输出)流提供了一条通道程序&#xff0c;可以使用这条通道把源中的字节序列送到目的地。虽然 I/O 流疆盘文件存取有关&#xff0c;但是程序的源和目…

启动dubbo消费端过程提示No provider available for the service的问题定位与解决

文/朱季谦 某次在启动dubbo消费端时&#xff0c;发现无法从zookeeper注册中心获取到所依赖的消费者API&#xff0c;启动日志一直出现这样的异常提示 Failed to check the status of the service com.fte.zhu.api.testService. No provider available for the service com.fte…

一道简单的积分题目

题目如下图&#xff1a; 解法1&#xff1a; 解法2&#xff1a; 解法3&#xff1a; 错误做法&#xff1a; 在 x ∈ ( 0 , ∞ ) 上有 ln ⁡ x < x &#xff0c;令 f ( x ) ln ⁡ x 1 x 2 &#xff0c; g ( x ) &#xff1d; x 1 x 2 ∴ f ( x ) < g ( x ) &#x…

中贝通信-603220 三季报分析(20231120)

中贝通信-603220 基本情况 公司名称&#xff1a;中贝通信集团股份有限公司 A股简称&#xff1a;中贝通信 成立日期&#xff1a;1999-12-29 上市日期&#xff1a;2018-11-15 所属行业&#xff1a;软件和信息技术服务业 周期性&#xff1a;1 主营业务&#xff1a;通信网络技术服务…

车载毫米波雷达行业发展1——概述

1.1 毫米波雷达定义及产品演进 1.1.1 毫米波雷达定义 毫米波雷达(mmWave Radar)是指工作在毫米波波段的雷达&#xff0c;其频域介于 30&#xff5e;300GHz&#xff0c;波长1~10mm。毫米波雷达稳定性高&#xff0c;抗干扰能力强&#xff0c;可穿透雾、烟、灰尘环境&#xff0…

Microsoft Visual Studio 2019下载及安装流程记录

第一周任务&#xff1a; 1.笔记本上安装vc2019的环境 2.再把OpenCV安装上 3.根据网上的教程&#xff0c;试着写几个opencv的程序 一、安装Visual Studio 2019社区版 首先先完成安装vc2019的环境&#xff0c; 因为&#xff1a; Microsoft Visual C是用于C编程的工具集合&am…

ATTCK 十大免费 工具和资源

01 eBook: Getting Started with ATT&CK 这本免费电子书将有关威胁情报、检测和分析、对手模拟和红队以及评估和工程的博客文章中的内容汇集到一个方便的软件包中。 02 CALDERA CALDERA是一个网络安全平台&#xff0c;旨在轻松自动化对手仿真&#xff0c;协助手动红队并自…

【鸿蒙最新全套教程】<HarmonyOS第一课>1、运行Hello World

下载与安装DevEco Studio 在HarmonyOS应用开发学习之前&#xff0c;需要进行一些准备工作&#xff0c;首先需要完成开发工具DevEco Studio的下载与安装以及环境配置。 进入DevEco Studio下载官网&#xff0c;单击“立即下载”进入下载页面。 DevEco Studio提供了Windows版本和…