web-dev-qa-db-ja.com

SQLAlchemy:クエリ内のオブジェクトの列の選択

SQLAlchemyのqueryメソッドで照会される列を制御しながら、照会しているオブジェクトのインスタンスを返すことはできますか(部分的に設定されていますが)?

または、SQLAlchemyがSELECT *を実行してオブジェクトにマップする必要がありますか?

(個々の列のクエリが可能であることは知っていますが、結果はオブジェクトにマップされず、名前付きタプルのコンポーネントにのみマップされます)。

たとえば、Userオブジェクトの属性がuserid、name、password、およびbioであるが、クエリが返すオブジェクトのuseridとnameのみを入力する場合は、次のようにします。

# hypothetical syntax, of course:
for u in session.query(User.columns[userid, name]).all():
    print u

印刷されます:

<User(1, 'bob', None, None)> 
<User(2, 'joe', None, None)>
...

これは可能ですか?もしそうなら、どのように?

22
kes

個々の列に対してクエリを実行できます。これは、テンプレートなどに渡すだけの場合、実際にはマップされたオブジェクトとほとんど同じように機能する名前付きタプルを返します。

http://www.sqlalchemy.org/docs/orm/tutorial.html#querying

または、構成またはオプションを使用して、マップされたクラスのさまざまな列を「据え置き」として設定できます。

http://docs.sqlalchemy.org/en/latest/orm/loading_columns.html#deferred-column-loading

「defer_everything_but()」と呼ばれるものの古いチケットがtracにあります。誰かがテストを提供したいと思った場合など、機能を追加できない理由がない場合は、ここにクイックバージョンがあります。

from sqlalchemy.orm import class_mapper, defer
def defer_everything_but(entity, cols):
    m = class_mapper(entity)
    return [defer(k) for k in 
            set(p.key for p 
                in m.iterate_properties 
                if hasattr(p, 'columns')).difference(cols)]

s = Session()
print s.query(A).options(*defer_everything_but(A, ["q", "p"]))

defer()は実際には複数を受け入れ、チケット#2250を追加する必要があります(編集:コメントに記載されているように、これは0.9の load_only() として)

18
zzzeek

私のために働いた簡単な解決策は:

users = session.query(User.userid, User.name)
for user in users:
    print user

印刷されます:

<User(1, 'bob')> 
<User(2, 'joe')>
...
15
Eli

load_onlyの最新のドキュメントはこちら

http://docs.sqlalchemy.org/en/latest/orm/loading_columns.html#load-only-cols

これをモデル定義レベルで制御する方法を検討している場合は、deferredを使用します

http://docs.sqlalchemy.org/en/latest/orm/loading_columns.html#deferred

5
Devi