SQLAlchemy使用load_only与distinct

时间:2017-06-30 09:21:24

标签: python python-3.x sqlalchemy

我正在尝试使用与SQLAlchemy不同的函数,但它似乎不起作用。我准备了一个小例子,你可以看到我的问题:

#-*- coding: utf-8 -*-
from sqlalchemy import create_engine,Column, Integer
from sqlalchemy.orm import sessionmaker,load_only
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///:memory:')
Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base()

class my_class(Base):
    __tablename__ = 'my_table'
    id= Column(Integer, primary_key=True)
    data= Column(Integer)

Base.metadata.create_all(engine)

for i in range(10):
    p=my_class()
    p.id=i
    p.data=55
    session.add(p)
session.commit()

s=session.query(my_class).distinct(my_class.data).options(load_only(my_class.data))

print (s)
for a in s.all():
    print (a.id,a.data)

执行此操作我希望输出如下:

SELECT my_table.data AS my_table_data 
FROM my_table
None 55

但相反,我得到了这个:

SELECT DISTINCT my_table.id AS my_table_id, my_table.data AS my_table_data 
FROM my_table
0 55
1 55
2 55
3 55
4 55
5 55
6 55
7 55
8 55
9 55

我做错了什么?

1 个答案:

答案 0 :(得分:3)

如果查询完整的ORM实体,推迟主键是没有意义的,因为an entity must have an identity so that a unique row can be identified in the database table。因此,虽然您拥有load_only(),但查询中包含主键。如果您只想要数据,则应该专门查询:

In [12]: session.query(my_class.data).distinct().all()
2017-06-30 12:31:49,200 INFO sqlalchemy.engine.base.Engine SELECT DISTINCT my_table.data AS my_table_data 
FROM my_table
2017-06-30 12:31:49,200 INFO sqlalchemy.engine.base.Engine ()
Out[12]: [(55)]

实际上有一个issue where having load_only() did remove the primary key from the select list,它是fixed in 0.9.5

  

[orm] [bug] 修改了orm.load_only()的行为,以便始终将主键列添加到要“未延期”的列列表中;否则,ORM无法加载行的标识。显然,可以推迟映射的主键,ORM将失败,但尚未更改。但是由于load_only基本上是在说“除了X之外的所有东西”,因此PK cols不是这种推迟的一部分更为重要。