灵活使用 SQLAlchemy 中的 ORM 查询
之前做查询一直觉得直接拼 SQL 比较方便,用了 SQLAlchemy 的 ORM 查询之后,发现也还可以,还提高了可读性。
这篇文章主要说说 SQLAlchemy 常用的 ORM 查询方式,偏实践。看了之后,对付开发中的查询需求,我觉得可以满足不少。
为方便说明,假设有如下数据
图书表 books
+----+--------+--------------------------+-------+
| id | cat_id | name | price |
+----+--------+--------------------------+-------+
| 1 | 1 | 生死疲劳 | 40.40 |
| 2 | 1 | 皮囊 | 31.80 |
| 3 | 2 | 半小时漫画中国史 | 33.60 |
| 4 | 2 | 耶路撒冷三千年 | 55.60 |
| 5 | 2 | 国家宝藏 | 52.80 |
| 6 | 3 | 时间简史 | 31.10 |
| 7 | 3 | 宇宙简史 | 22.10 |
| 8 | 3 | 自然史 | 26.10 |
| 9 | 3 | 人类简史 | 40.80 |
| 10 | 3 | 万物简史 | 33.20 |
+----+--------+--------------------------+-------+
分类表 categories
+----+--------------+
| id | name |
+----+--------------+
| 1 | 文学 |
| 2 | 人文社科 |
| 3 | 科技 |
+----+--------------+
ORM 对象定义如下
注意:本文 Python 代码在以下环境测试通过
- Python 3.6.0
- PyMySQL 0.8.1
- SQLAlchemy 1.2.8
# coding=utf-8
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Numeric
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
engine = create_engine('mysql+pymysql://username:password'
'@127.0.0.1:3306/db_name?charset=utf8')
Session = sessionmaker(bind=engine)
session = Session()
def to_dict(self):
return {c.name: getattr(self, c.name, None)
for c in self.__table__.columns}
Base.to_dict = to_dict
class Book(Base):
__tablename__ = 'books'
id = Column(Integer, primary_key=True)
cat_id = Column(Integer)
name = Column('name', String(120))
price = Column('price', Numeric)
class Category(Base):
__tablename__ = 'categories'
id = Column(Integer, primary_key=True)
name = Column('name', String(30))
好了,下面进入正题。
1 根据主键获取记录
当我们获取图书的详情时,很容易用到。
book_id = 1
book = session.query(Book).get(book_id)
print(book and book.to_dict())
直接 get(primary_key) 就得到结果
{'id': 1, 'cat_id': 1, 'name': '生死疲劳',
'price': Decimal('40.40')}
当然,这样也可以
book_id = 1
book = session.query(Book) \
.filter(Book.id == book_id) \
.first()
print(book and book.to_dict())
不过,还是前一种方式简洁一些。