SQLAlchemy 初探

SQLAlchemy是一个使用Python语言开发的对象关系映射(ORM)框架,具有高性能、易用性强、可扩展性高等特点。

基本用法介绍

本文基于现时的SQLAlchemy稳定版本1.3.23进行说明。

建立连接

1
2
3
4
5
6
7
from sqlalchemy import create_engine
## 1. sqlite, python内建支持
engine_1 = create_engine('sqlite://test', echo=True) # echo=True时,logger中能看到生成的所有SQL
## 2. postgresql, 使用 psycopg2 作为 驱动
engine_2 = create_engine('postgresql+psycopg2://<username>:<password>@<host>/<dbname>)
## 3. mysql/mariadb, 使用 pymysql 作为 驱动
engine_3 = create_engine('mysql+pymysql://<username>:<password>@<host>/<dbname>')
  • 上文所述的驱动,均需要使用 pip 进行安装后才可使用。
  • 此处的连接为惰性连接,当且仅当第一次要求它对数据库执行任务时建立。

声明映射

1
2
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
  • ORM框架通过读取接下来定义的类,将这些类映射到相应的数据库表中。
  • SQLAlchemy通过使用一个全局单例的称为声明性基类的对象,完成以上行为。

声明映射类

1
2
3
4
5
6
7
8
9
10
11
12
from sqlalchemy import Column, Integer, String
class User(Base):
__tablename__ = 'users'

id = Column(Integer, primary_key=True) ## 注意,此处的id为Python的一个关键字
name = Column(String)
fullname = Column(String)
nickname = Column(String)

def __repr__(self): ## 重写内置方法
return "<User(name='%s', fullname='%s', nickname='%s')>" % (
self.name, self.fullname, self.nickname)
  • Base 为 早先声明的声明性基类,映射类需要继承该类
  • 每一个映射类需要声明 __tablename__ 属性作为所映射的表名,以及至少一个Column,它是主键的一部分。
  • 可以定义一个方法,用来展示该映射类某一对象的属性值。

进行查询

此处使用Session进行查询。开始查询之前,需要先建立Session。ORM 对数据库的“句柄”是 Session。

建立Session

1
2
3
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
session = Session()
  • 此处的engine 为 1.1. 中建立连接时创建的。

增加单条数据
1
2
3
ed_user = User(name='ed', fullname='Ed Jones', nickname='edsnickname')
session.add(ed_user)
session.commit() # 提交更改
批量增加数据
1
2
3
4
ed_user = User(name='ed', fullname='Ed Jones', nickname='edsnickname')
fr_user = User(name='fr', fullname='Frank Kings', nickname='frsnickname')
user_list = [ed_user, fr_user]
session.add_all(user_list) # 提交更改

1
2
session.query(User).all()   ## 查询users表中全部内容
session.query(User.name, User.fullname).all() ## 查询users表中全部含指定列的内容
  • all() 函数,返回一个模型类组成的列表
  • first() 函数,返回一个模型类对象
filter_by() 函数
1
2
3
my_user_1 = session.query(User).filter_by(name="fr").first()	## 查询 users 表中 列 name 等于 fr 的首条数据
my_user_2 = session.query(User).filter_by(name="fr" and fullname='Ed Jones').first() ## 与查询
my_user_3 = session.query(User).filter_by(name="fr" or name="ed").first() ## 或查询
  • 可以使用 python 的正常参数传递方法传递条件,指定列名时不需要额外指定类名。
  • 参数名对应名类中的属性名,只能使用 =,不能使用 > < 等条件。
  • 支持不同条件的组合,见以上中的与查询与或查询。
filter() 函数
1
2
3
4
5
my_user_1 = session.query(User).filter(User.name == "fr").first()	## 查询 users 表中 列 name 等于 fr 的首条数据
my_user_2 = session.query(User).filter(User.name != "fr").first() ## 查询 users 表中 列 name 不等于 fr 的首条数据
my_user_3 = session.query(User).filter(User.name.like("%fr%")).first() ## LIKE 模糊查询
my_user_4 = session.query(User).filter(User.name.in_(['f', 'r'])).first() ## IN 条件查询, 注意此处函数名为in_
my_user_5 = session.query(User).filter(~User.name.in_(['f', 'r'])).first() ## NOT IN 条件查询, 注意此处为in_的非(~)
  • 可以像写 sql 的 where 条件那样写 > < 等条件,相等的条件为 ==。

  • 使用列名时,需要通过 类名.属性名 的方式。

  • 如果不加上.all().first(),结果为一sql语句。

  • 与查询:两种方式

    • 链式调用 filter() 函数

      1
      my_user = session.query(User).filter(User.name == "fr").filter(User.fullname == "Frank Kings").first()
    • 导入and_函数:

      1
      2
      from sqlalchemy import and_
      my_user = session.query(User).filter(and_(User.name == "fr", User.fullname == "Frank Kings")).first()
  • 或查询: 导入or_函数

    1
    2
    from sqlalchemy import or_
    my_user = session.query(User).filter(or_(User.name == "fr", User.fullname == "Frank Kings")).first()

  • 先查询,获取到实体之后再进行修改

    1
    2
    3
    my_user_1.name = "wangxiang"
    my_user_1.fullname = "Wang Xiang"
    session.commit() # 提交更改
  • 直接在query()之后使用update() 函数,传入字典

    1
    2
    3
    4
    5
    update_dict = {
    name: "wangxiang",
    fullname: "Wang Xiang"
    }
    session.query(User).filter(User.name == "fr").update(update_dict)

  • 先查询,获取到实体后再对实体进行删除

    1
    session.delete(my_user_1)

未完待续。。