SQLAlchemy简介

作者: 爱折腾的大懒猪 | 来源:发表于2019-06-10 05:19 被阅读8次

SQLAlchemy是SQL的对象关系映射(ORM, Object-Relational Mapping)的工具. 和传统直接操作SQL相比, 使用SQLAlchemy的对象来操作数据库更为直观.

例如, 传统Python的DB-API返回的数据库表是列表, 内含多个元组, 每个元组代表一行数据. 这种数据结构并不直观, 而使用对象的话会更为直观:

# DB-API 返回的数据库表结构
[
    ('1', 'Michael'),
    ('2', 'Bob'),
    ('3', 'Adam')
]

# 使用类来表达表的结构
class User(object):
    def __init__(self, id, name):
        self.id = id
        self.name = name

[
    User('1', 'Michael'),
    User('2', 'Bob'),
    User('3', 'Adam')
]

安装很简单:

# PIP
pip install sqlalchemy
# Conda
conda install sqlalchemy

使用示例

维基示例: 这里创建一个电影对象和导演对象, 其中, 电影对象使用外键来指定导演表的对象.

创建Python类

  • 首先需要创建sqlalchemy的ORM的基类: declarative_base
  • 使用基类进行继承. 要指定表名, 用__tablename__
  • 如果需要外键, 用relation或者relationship(等价) 绑定关系.
  • 对象初始化后, 如有外键, 也要指定外键(哪边初始化外键都可以)
''' 创建两个Python类以及DBMS中对应的数据表'''

# 导入基础类, create_engine方法
from sqlalchemy import Integer, String, ForeignKey, Column, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relation, sessionmaker

# 创建对象的基类
Base = declarative_base()
 
# 定义自定义的类对象
class Movie(Base):
    # 表的名字
    __tablename__ = 'movies'
   
    # 表的结构
    id = Column(Integer, primary_key=True)
    title = Column(String(255), nullable=False)
    year = Column(Integer)
    directed_by = Column(Integer, ForeignKey('directors.id'))
 
    # 外键对象, 上面directed_by使用
    director = relation("Director", backref='movies', lazy=False)
 
    # 类的初始化和表达 
    def __init__(self, title=None, year=None):
        self.title = title
        self.year = year
    def __repr__(self):
        return "Movie(%r, %r, %r)" % (self.title, self.year, self.director)
 
# 上述类中使用的ForeignKey, Director类.
class Director(Base):
    __tablename__ = 'directors'
 
    id = Column(Integer, primary_key=True)
    name = Column(String(50), nullable=False, unique=True)
 
    def __init__(self, name=None):
        self.name = name
 
    def __repr__(self):
        return "Director(%r)" % (self.name)

# 创建Movie类对象, 并将director指向新的Director对象. 
m1 = Movie("Star Trek", 2009)
m1.director = Director("JJ Abrams")

# 创建Director对象, 并创建两部电影进行绑定
# 依赖于 relation("Director", backref='movies', lazy=False) 
d2 = Director("George Lucas")
d2.movies = [Movie("Star Wars", 1977), Movie("THX 1138", 1971)]

初始化数据库连接

  • 使用create_engine 来初始化数据库连接引擎, 需要指定各种信息. 例如create_engine('mysql+mysqlconnector://root:password@localhost:3306/test')
  • 返回的引擎, 可以用来创建数据库连接Session, 从而实现对数据库的操作.
  • 操作数据库, 例如 add, query, commit, rollback, close等. 和Python操作SQL类似.
# 初始化数据库连接
engine = create_engine('dbms://user:pwd@host/dbname')
Base.metadata.create_all(engine)

''' 插入数据, 并使电影和导演对象可以互相引用'''
# 创建DBSession类型和对象. 
# 这个Session对象相当于数据库连接. 
Session = sessionmaker(bind=engine)
session = Session()

# 数据库更新
try:
    session.add(m1)
    session.add(d2)
    session.commit()
except:
    session.rollback()

# 关闭数据库
session.close()

查询数据

# 如果前面的session没关, 可以直接查询, 这里假设关了
session = Session()
# 创建Query查询. 这里是查询所有结果
alldata = session.query(Movie).all()
for somedata in alldata:
    print somedata

'''
Movie('Star Trek', 2009L, Director('JJ Abrams'))
Movie('Star Wars', 1977L, Director('George Lucas'))
Movie('THX 1138', 1971L, Director('George Lucas'))
'''

# 以下查询使用filter(相当于where)
# 最后用`one()` 返回唯一行, `all()`返回所有行
movie1 = session.query(Movie).filter(Movie.id=='1').one()

注意, 当设置外键关系是lazy=False时, 实际发起的SQL是:

SELECT movies.id, movies.title, movies.year, movies.directed_by, directors.id, directors.name 
FROM movies LEFT OUTER JOIN directors ON directors.id = movies.directed_by

默认的外键关系是lazy=True, 此时将首先发起对电影列表的查询, 并在必要时(延迟加载逐一查询导演的名称:

SELECT movies.id, movies.title, movies.year, movies.directed_by 
FROM movies

SELECT directors.id, directors.name
FROM directors 
WHERE directors.id = %s

实际上, ORM框架的作用就是把数据库表的一行记录与一个对象互相做自动转换。

相关文章

网友评论

    本文标题:SQLAlchemy简介

    本文链接:https://www.haomeiwen.com/subject/cszoxctx.html