• 我们在哪一颗星上见过 ,以至如此相互思念 ;我们在哪一颗星上相互思念过,以至如此相互深爱
  • 我们在哪一颗星上分别 ,以至如此相互辉映 ;我们在哪一颗星上入睡 ,以至如此唤醒黎明
  • 认识世界 克服困难 洞悉所有 贴近生活 寻找珍爱 感受彼此

SQLAlchemy

python知识点 云涯 4个月前 (08-02) 462次浏览

概述

SQLAlchemy是一套使用python来处理数据的的工具包。

两个核心概念是ORM和Core。ORM是对象关系映射,是通过python操作数据的面向对象的工具。Core是使用SQL语句操作数据的工具。

对象关系映射(ORM)

引擎Engine

连接 (Connection)

SQL 表达式语言 (SQL Expression Language)

方言 (Dialect)

知识点

单表继承

想象你有一个水果店,卖各种水果:苹果、香蕉、橙子等。单表继承就像把所有水果的信息都记录在一张大表格上。这张表格有几列是所有水果共有的(比如“名称”、“价格”),还有一些列只适用于特定水果(比如苹果的“品种”,香蕉的“产地”)。

  • 基类(Base Class):就像水果店的“水果”这个总称。它定义了所有水果的共同属性(列)。
  • 子类(Subclass):就像具体的水果种类,比如“苹果”、“香蕉”。它们继承基类的属性,还可以有自己独特的属性。
  • 鉴别器列(Discriminator Column):就像表格上的一列,用来区分不同种类的水果。比如,你可以有一列叫“类型”,它的值可以是“苹果”、“香蕉”等。
  • 多态查询(Polymorphic Query):就像你问店员:“给我所有价格低于 5 元的水果”,店员会把符合条件的苹果、香蕉、橙子都拿给你,而不仅仅是某一种水果。
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Fruit(db.Model): # 基类
__tablename__ = 'fruits'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
price = db.Column(db.Float)
type = db.Column(db.String(50)) # 鉴别器列
__mapper_args__ = {
'polymorphic_identity': 'fruit', # 基类的标识
'polymorphic_on': type # 指定鉴别器列
}

class Apple(Fruit): # 子类
__mapper_args__ = {'polymorphic_identity': 'apple'}
variety = db.Column(db.String(50)) #品种

class Banana(Fruit): # 子类
__mapper_args__ = {'polymorphic_identity': 'banana'}
origin = db.Column(db.String(50)) # 产地

 

 

 

Flask-SQLAlchemy

知识点 描述 扩展
db.Model db.Model是所有模型的基类。

映射到数据库表,每一个基础db.Model的类都映射到数据库中的一个表。

关系映射:可以定义模型之间的一对多,多对多关系。

db.Column 用来定义数据库表 列 的类,定义了表的字段及属性,比如数据库类型、主键等。
db.relationship

用来定义模型之间的关系,比如一对多、多对多关系。

 

backref 参数:用于创建反向引用,即在定义两个模型之间的关系时,让每个模型都可以通过对方轻松访问彼此。可以自定义名字。
db.session db.session 是 SQLAlchemy 提供的一个会话(session)对象,它用于执行数据库操作,如查询、插入、更新和删除。会话对象负责在数据库和程序之间管理对象,并处理事务。 查询数据:users = db.session.query(User).all()

添加新记录:

new_user = User(username=’newuser’)
db.session.add(new_user)
db.session.commit() # 提交事

更新记录:

user = db.session.query(User).filter_by(id=1).first()
user.username = ‘updateduser’
db.session.commit()

删除记录:

user = db.session.query(User).filter_by(id=1).first()
db.session.delete(user)
db.session.commit()

在类中定义列信息

class Agents(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(191))

SQLAlchemy 需要重新定义一次列信息是因为它使用 ORM(对象关系映射)来映射数据库表到 Python 类。这种映射需要在类定义中明确列的信息,以便 SQLAlchemy 可以生成和操作数据库表结构。而 PyMySQL 是一个底层的数据库驱动,直接执行 SQL 语句,不需要 ORM 的这种映射过程

connection = pymysql.connect(host='localhost', user='user', password='passwd', database='db')
cursor = connection.cursor()
cursor.execute("SELECT id, username FROM users")

配置

flask_sqlalchemy.config

flask_sqlalchemy.config.SQLALCHEMY_DATABASE_URI: 告诉 Flask-SQLAlchemy 你用的是什么类型的数据库(SQLite、PostgreSQL、MySQL 等),以及数据库在哪里

SQLALCHEMY_ENGINE_OPTIONS: 字典, 告诉 Flask-SQLAlchemy 如何与数据库进行更精细的交互

SQLALCHEMY_BINDS: 如果你有多个数据库,这个配置可以让你为每个数据库设置不同的引擎选项

SQLALCHEMY_ECHO:

这个配置主要用于调试。如果启用它,Flask-SQLAlchemy 就会把你发送给数据库的指令(SQL 命令)打印出来,方便你查看。

SQLALCHEMY_RECORD_QUERIES:这个配置也是用于调试的。它会记录你的应用在一次请求中向数据库发送的所有查询,方便你分析。

SQLALCHEMY_TRACK_MODIFICATIONS:这个配置会监视你对数据库表所做的更改。

3.1 版中的更改:删除了 SQLALCHEMY_COMMIT_ON_TEARDOWN

默认驱动程序选项

为 SQLite 和 MySQL 引擎设置了一些默认选项,使其在 Web 应用中默认情况下更易于使用。 SQLite 相对文件路径是相对于 Flask 实例路径而不是当前工作目录。内存数据库使用静态池和 check_same_thread 在请求之间工作。

MySQL(和 MariaDB)服务器被配置为删除空闲 8 小时的连接,这可能会导致类似 2013: Lost connection to MySQL server during query 的错误。默认的 pool_recycle 值为 2 小时(7200 秒),用于在该超时之前重新创建连接。

引擎配置优先级

由于 Flask-SQLAlchemy 支持多个引擎,因此有关于哪个配置覆盖其他配置的规则。

大多数应用程序将只有一个数据库,只需要使用 SQLALCHEMY_DATABASE_URISQLALCHEMY_ENGINE_OPTIONS

如果向 SQLAlchemy 提供了 engine_options 参数,它将为所有引擎设置默认选项。 SQLALCHEMY_ECHO 为所有引擎设置 echoecho_pool 的默认值。 SQLALCHEMY_BINDS 中每个引擎的选项都会覆盖这些默认值。 SQLALCHEMY_ENGINE_OPTIONS 会覆盖 SQLALCHEMY_BINDS 中的 None 键,SQLALCHEMY_DATABASE_URI 会覆盖该引擎选项中的 url 键。

超时

某些数据库可能会配置为在一段时间后关闭不活动的连接。MySQL 和 MariaDB 默认情况下是这样配置的,但数据库服务也可能会配置这种类型的限制。这可能会导致类似 2013: Lost connection to MySQL server during query 的错误。 如果遇到此错误,请尝试将引擎选项中的 pool_recycle 设置为小于数据库超时值的值。 或者,如果您希望数据库经常关闭连接(例如,如果它在可能会重新启动的容器中运行),可以尝试设置 pool_pre_ping。 有关详细信息,请参阅 SQAlchemy 关于处理断开连接的文档。

模型和表

使用 db.Model 类定义模型,或使用 db.Table 类创建表。两者都处理 Flask-SQLAlchemy 的绑定键,以便与特定引擎关联。

  • db.Model 类定义模型: 这是最常用的方式,更方便、更 Pythonic。Flask-SQLAlchemy 会根据你的模型自动创建对应的表。
  • db.Table 类直接创建表: 这种方式更灵活,但需要你手动写 SQL。

初始化基类

想象一下,你正在设计一系列房屋。虽然每栋房子都有独特之处(比如卧室数量、颜色),但它们也有一些共同点(比如都有门窗、都需要地基)。在面向对象编程中,基类就像房子的通用蓝图,定义了所有房子都具备的基本特征。

SQLAlchemy 2.x 为你的模型提供了几个可能的基类:DeclarativeBaseDeclarativeBaseNoMeta

  • DeclarativeBase 这是最常用的基类,提供了声明式模型定义的全部功能。
  • DeclarativeBaseNoMeta 这是一个更轻量级的基类,不包含 MetaData 对象。如果你不需要自定义约束命名约定,可以选择这个基类。

你可以选择其中一个创建子类:

from sqlalchemy.orm import DeclarativeBase

class Base(DeclarativeBase):
pass

如果你希望启用 SQLAlchemy 对数据类的原生支持,可以添加 MappedAsDataclass 作为另一个父类。

from sqlalchemy.orm import DeclarativeBase, MappedAsDataclass

class Base(DeclarativeBase, MappedAsDataclass):
pass

自定义 MetaData 对象

你可以选择性地使用自定义的 MetaData 对象来构建 SQLAlchemy 对象。这允许你指定自定义的约束命名约定,使约束名称保持一致和可预测,这在使用 Alembic 进行数据库迁移时非常有用。

初始化扩展

定义好基类后,就可以使用 SQLAlchemy 构造函数创建 db 对象。

定义模型

要定义模型类,请继承 db.Model。与普通的 SQLAlchemy 不同,Flask-SQLAlchemy 的模型会在没有设置 __tablename__ 且定义了主键列的情况下自动生成表名。

from sqlalchemy.orm import Mapped, mapped_column

class User(db.Model):
id: Mapped[int] = mapped_column(primary_key=True)
username: Mapped[str] = mapped_column(unique=True)
email: Mapped[str]

定义数据表

要定义数据表,请创建 db.Table 的实例。与普通的 SQLAlchemy 不同,不需要提供 metadata 参数,Flask-SQLAlchemy 会根据 bind_key 参数选择合适的 metadata,或者使用默认的。

映射现有表 (Reflecting Tables)

如果你连接的数据库中已经存在表,SQLAlchemy 可以自动检测模式并创建具有相应列的表对象。这个过程称为映射(reflection)。你可以将这些表对象分配给模型类的 __table__ 属性,而不是自己定义完整的模型。

with app.app_context():
db.reflect()

class Book(db.Model):
__table__ = db.metadata.tables["book"]

 

 

 

 

 

 

 

 

 

 

 


云涯历险记 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:SQLAlchemy
喜欢 (0)