PonyORM - python的新一代黑魔法级别ORM

简单的例子,来自官网

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的黑魔法在哪里呢?

  1. 首先select(x for x in ...) 这是一个generator comprehension,和list comprehension不同的是,返回的是一个惰性求值的生成器,于是
  2. 该表达式bytecode可以反编译
  3. 把Python的AST翻译成SQL的AST
  4. 分离和优化查询。
  5. 把SQL AST生成为特定数据库的query
  6. 执行SQL query
  7. 把返回构造成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