Python 数据持久化 - SQLAlchemy


任何关系数据库都将数据保存在表中。表结构定义了属性的数据类型,这些属性基本上只是基本数据类型,映射到相应的Python内置数据类型。但是,Python 的用户定义对象无法持久存储到 SQL 表或从 SQL 表中检索。

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

如果必须将对象存储在关系数据库中,则在执行 INSERT 查询之前,应首先将其实例属性解构为 SQL 数据类型。另一方面,从 SQL 表检索的数据是主要类型。所需类型的 Python 对象必须通过在 Python 脚本中使用来构造。这就是对象关系映射器有用的地方。

对象关系映射器 (ORM)

对象关系映射器( ORM) 是类和 SQL 表之间的接口。将Python类映射到数据库中的某个表,从而自动进行对象和SQL类型之间的转换。

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

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

SQLALchemy 库包括ORM API和 SQL 表达式语言(SQLAlchemy 核心)。表达式语言直接执行关系数据库的原始构造。

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

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

  • 火鸟
  • 微软SQL服务器
  • MySQL
  • 甲骨文
  • PostgreSQL
  • SQLite
  • 赛贝斯
奥姆

使用 pip 实用程序安装 SQLAlchemy 既简单又直接。

pip install sqlalchemy

要检查 SQLalchemy 是否已正确安装及其版本,请在 Python 提示符下输入以下内容 -

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

与数据库的交互是通过作为create_engine()函数的返回值获得的 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 包含声明性基类。它充当模型类和映射表的目录。

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

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

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

  • 大整数
  • 布尔值
  • 日期
  • 约会时间
  • 漂浮
  • 整数
  • 数字
  • 小整数
  • 细绳
  • 文本
  • 时间

以下代码是将名为 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 表,请执Behave基类定义的 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()

这是在学生表中添加记录的完整代码。执行时,控制台会显示相应的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()

控制台输出

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

会话对象还提供 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()