PonyORM - python的新一代黑魔法级别ORM
Posted | archive
简单的例子,来自官网
python的查询代码:
select(c for c in Customer
if sum(c.orders.price) > 1000)
通过PonyORM翻译成SQL:
SELECT "c"."id"
FROM "Customer" "c"
LEFT JOIN "Order" "order-1"
ON "c"."id" = "order-1"."customer"
GROUP BY "c"."id"
HAVING coalesce(SUM("order-1"."total_price"), 0) > 1000
以前觉得peewee的查询语法很clever,比Django那种丑爆的 price__gt=1000
好出一条街。那么PonyORM就超出其他python ORM一条银河系了。
这个PonyORM的黑魔法在哪里呢?
- 首先
select(x for x in ...)
这是一个generator comprehension,和list comprehension不同的是,返回的是一个惰性求值的生成器,于是 - 该表达式bytecode可以反编译
- 把Python的AST翻译成SQL的AST
- 分离和优化查询。
- 把SQL AST生成为特定数据库的query
- 执行SQL query
- 把返回构造成python对象,并且缓存。
出自PonyORM开发者 u/amalashkevich。更加详细的黑魔法解释可以在stackoverflow上看到。
可以说Peewee和PonyORM的设计才是优雅的。但是PonyORM更加高级,基本接近了LINQ和超过了Hibernate HQL。
顺便提一下,有一个另外类似的ORM——PQL,用于MongoDB:
比如:
pql.find("a > 1 and b == 'foo' or not c.d == False")
翻译成MongoDB的查询:
{'$or': [{'$and': [{'a': {'$gt': 1}}, {'b': 'foo'}]}, {'$not': {'c.d': False}}]}
很可惜它是基于字符串的翻译,而不是原生python表达式。
其他讨论
Comments