Python数据持久性 SQLAlchemy
任何关系型数据库都将数据保存在表中。表结构定义了属性的数据类型,基本上只有主数据类型,它们被映射到Python的相应内置数据类型。然而,Python的用户定义对象不能持久地存储和检索到/来自SQL表。
这是SQL类型和面向对象的编程语言(如Python)之间的一个差异。SQL没有与之相当的数据类型,如dict、tuple、list或任何用户定义的类。
如果你必须在关系数据库中存储一个对象,在执行INSERT查询之前,它的实例属性应该首先被解构为SQL数据类型。另一方面,从 SQL 表中检索的数据是主类型的。所需类型的Python对象必须通过使用Python脚本来构建。这就是对象关系映射器的用处。
对象关系映射器 (ORM)
对象关系映射器 (ORM)是一个类和一个SQL表之间的接口。一个Python类被映射到数据库中的某个表,因此对象和SQL类型之间的转换被自动执行。
在Python代码中编写的学生类被映射到数据库中的学生表。因此,所有的CRUD操作都是通过调用该类的相关方法来完成的。这消除了在Python脚本中执行硬编码的SQL查询的需要。
因此ORM库作为原始SQL查询的抽象层,可以帮助快速开发应用程序。 SQLAlchemy 是一个流行的Python对象关系映射器。对模型对象状态的任何操作都是与数据库表中的相关行同步的。
SQLALchemy库包括 ORM API 和SQL表达式语言( SQLAlchemy核心 )。表达式语言直接执行关系数据库的原始结构。
ORM是在SQL表达式语言之上构建的高水平和抽象化的使用模式。可以说,ORM是表达式语言的一种应用用法。我们将讨论SQLAlchemy ORM API,并在本专题中使用SQLite数据库。
SQLAlchemy通过各自的DBAPI实现,使用方言系统与各种类型的数据库进行通信。所有的方言都需要安装一个合适的DBAPI驱动程序。以下类型的数据库的方言包括-
- Firebird
- Microsoft SQL Server
- MySQL
- Oracle
- PostgreSQL
- SQLite
- Sybase
SQLAlchemy的安装很简单,使用pip工具。
pip install sqlalchemy
要检查SQLalchemy是否正确安装及其版本,请在Python提示符下输入以下内容– 1.
>>> 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()
下一步是定义一个模型类。它必须派生自base–如上所述的declarative_base类的对象。
将__tablename__
属性设置为你想在数据库中创建的表的名称。其他属性对应于字段。每个字段都是SQLAlchemy中的Column对象,其数据类型来自以下列表中的一个
- BigInteger
- Boolean
- Date
- DateTime
- Float
- Integer
- Numeric
- SmallInteger
- String
- Text
- 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)
要创建一个有相应结构的学生表,执行为基类定义的create_all()方法。
base.metadata.create_all(engine)
现在我们必须声明一个学生类的对象。所有的数据库事务,如从数据库中添加、删除或检索数据等,都由一个会话对象来处理。
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
sessionobj = Session()
存储在学生对象中的数据通过会话的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()方法来执行这个任务。查询对象由我们的学生模型的query()方法返回。
qry=seesionobj.query(Student)
使用该查询对象的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()