Python Data Persistence 简明教程

Python Data Persistence - SQLAlchemy

任何关系数据库中的数据都存储在表中。表结构定义了基本数据类型的属性数据类型,这些数据类型通常仅映射到 Python 的内置数据类型。但是,Python 的用户定义对象不能持久地存储到/检索自 SQL 表。

这是 SQL 类型与面向对象编程语言(如 Python)之间的差异。SQL 对其他对象(如 dict、元组、列表或任何用户定义的类)没有等效的数据类型。

如果你必须将对象存储在关系数据库中,则必须先将其实例属性解构为 SQL 数据类型,然后再执行 INSERT 查询。另一方面,从 SQL 表中检索到的数据为原始类型。必须使用所需类型的 Python 对象,才能在 Python 脚本中使用。这是对象关系映射工具发挥作用的地方。

Object Relation Mapper (ORM)

Object Relation Mapper (ORM) 是类与 SQL 表之间的接口。Python 类映射到数据库中的某个表中,这样对象和 SQL 类型之间的转换将自动执行。

用 Python 代码编写的 Students 类映射到数据库中的 Students 表中。因此,所有 CRUD 操作都是通过调用类的各个方法来完成的。这样消除了在 Python 脚本中执行硬编码 SQL 查询的需要。

因此,ORM 库充当对原始 SQL 查询的抽象层,有助于快速应用程序开发。 SQLAlchemy 是 Python 的流行对象关系映射器。对模型对象状态的任何操作都将与其在数据库表中的相关行同步。

SQLALchemy 库包含 ORM API 和 SQL 表达式语言( SQLAlchemy Core )。表达式语言直接执行关系数据库的基本构造。

ORM 是构建在 SQL 表达式语言之上的高级抽象化使用模式。可以说,ORM 是表达语言的应用。在该主题中,我们将讨论 SQLAlchemy ORM API 并使用 SQLite 数据库。

SQLAlchemy 通过使用方言系统使用它们各自的 DBAPI 实现与各种类型的数据库通信。所有方言都要求安装适当的 DBAPI 驱动程序。以下类型的数据库方言包括:

  1. Firebird

  2. Microsoft SQL Server

  3. MySQL

  4. Oracle

  5. PostgreSQL

  6. SQLite

  7. Sybase

orm

安装 SQLAlchemy 非常简单,使用 pip 程序包管理器。

pip install sqlalchemy

要检查 SQLalchemy 是否正确安装及其版本,请在 Python 提示符下输入以下命令:

>>> import sqlalchemy
>>>sqlalchemy.__version__
'1.3.11'

与数据库的交互通过作为 create_engine() 函数返回值获取的引擎对象来完成。

engine =create_engine('sqlite:///mydb.sqlite')

SQLite 允许创建内存中的数据库。内存中数据库的 SQLAlchemy 引擎创建如下:

from sqlalchemy import create_engine
engine=create_engine('sqlite:///:memory:')

如果你打算使用 MySQL 数据库,请使用其 DB-API 模块 – pymysql 和相关方言驱动程序。

engine = create_engine('mysql+pymydsql://root@localhost/mydb')

create_engine 有一个可选的 echo 参数。如果设置为 true,引擎生成的 SQL 查询将在终端上显示。

SQLAlchemy 包含 declarative base 类。它作为模型类和映射表的目录。

from sqlalchemy.ext.declarative import declarative_base
base=declarative_base()

下一步是定义模型类。它必须派生自基本对象 – 如上所述的 declarative_base 类。

*tablename* 属性设置为要创建的表在数据库中的名称。其他属性对应于字段。每个属性都是 SQLAlchemy 中的一个 Column 对象,并且其数据类型来自以下列表之一:

  1. BigInteger

  2. Boolean

  3. Date

  4. DateTime

  5. Float

  6. Integer

  7. Numeric

  8. SmallInteger

  9. String

  10. Text

  11. Time

以下代码是一个名为 Student 的模型类,它映射到 Students 表。

#myclasses.py
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Numeric
base=declarative_base()
class Student(base):
   __tablename__='Students'
   StudentID=Column(Integer, primary_key=True)
   name=Column(String)
   age=Column(Integer)
   marks=Column(Numeric)

要创建一个具有对应结构的 Students 表,请执行为基本类定义的 create_all() 方法。

base.metadata.create_all(engine)

我们现在必须声明一个 Student 类的对象。所有数据库事务(比如添加、删除或从数据库中检索数据等)都由 Session 对象处理。

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
sessionobj = Session()

存储在 Student 对象中的数据通过会话的 add() 方法在底层表中物理添加。

s1 = Student(name='Juhi', age=25, marks=200)
sessionobj.add(s1)
sessionobj.commit()

以下是向 students 表中添加记录的整个代码。在执行该代码时,将在控制台上显示相应的 SQL 语句日志。

from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from myclasses import Student, base
engine = create_engine('sqlite:///college.db', echo=True)
base.metadata.create_all(engine)

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
sessionobj = Session()
s1 = Student(name='Juhi', age=25, marks=200)
sessionobj.add(s1)
sessionobj.commit()

Console output

CREATE TABLE "Students" (
   "StudentID" INTEGER NOT NULL,
   name VARCHAR,
   age INTEGER,
   marks NUMERIC,
   PRIMARY KEY ("StudentID")
)
INFO sqlalchemy.engine.base.Engine ()
INFO sqlalchemy.engine.base.Engine COMMIT
INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
INFO sqlalchemy.engine.base.Engine INSERT INTO "Students" (name, age, marks) VALUES (?, ?, ?)
INFO sqlalchemy.engine.base.Engine ('Juhi', 25, 200.0)
INFO sqlalchemy.engine.base.Engine COMMIT

session 对象还提供 add_all() 方法,以在单个事务中插入多个对象。

sessionobj.add_all([s2,s3,s4,s5])
sessionobj.commit()

既然已在表中添加了记录,我们想要像 SELECT 查询一样从中提取记录。会话对象有 query() 方法来执行该任务。在我们的 Student 模型上,query() 方法会返回查询对象。

qry=seesionobj.query(Student)

使用此 Query 对象的 get() 方法提取与给定主键对应的对象。

S1=qry.get(1)

在执行此语句时,它在控制台上回显的相应 SQL 语句如下所示:

BEGIN (implicit)
SELECT "Students"."StudentID" AS "Students_StudentID", "Students".name AS
   "Students_name", "Students".age AS "Students_age",
   "Students".marks AS "Students_marks"
FROM "Students"
WHERE "Products"."Students" = ?
sqlalchemy.engine.base.Engine (1,)

query.all() 方法返回所有对象的列表,该列表可以使用循环来遍历。

from sqlalchemy import Column, Integer, String, Numeric
from sqlalchemy import create_engine
from myclasses import Student,base
engine = create_engine('sqlite:///college.db', echo=True)
base.metadata.create_all(engine)
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
sessionobj = Session()
qry=sessionobj.query(Students)
rows=qry.all()
for row in rows:
   print (row)

更新映射表中的记录非常容易。您所要做的就是使用 get() 方法提取记录,为所需的属性分配一个新值,然后使用会话对象提交更改。在下面,我们将 Juhi 学生的分数更改为 100。

S1=qry.get(1)
S1.marks=100
sessionobj.commit()

删除记录同样容易,只需从会话中删除所需的对象即可。

S1=qry.get(1)
Sessionobj.delete(S1)
sessionobj.commit()