2016-07-14 10 views
0

オブジェクトの属性を動的にクエリすることを検討しています。実行時に使用する属性(この場合は列)はわかりません。SQLAlchemyオブジェクト属性を使用した動的クエリ

class Product(Base): 
    __tablename__ = 'products' 

    sku = Column(String, primary_key=True) 
    list_price = Column(String) 
    status = Column(String) 
    url = Column(String) 
    special_price1 = Column(String) 
    special_price2 = Column(String) 
    special_price3 = Column(String) 

は、私は、リストの価格と異なるいくつかの属性に加えて、追加の特別価格を記述するSQLAlchemyの基底クラスProductを持っています。

これは、の下のクラスであり、'products'テーブルの列の報告と更新に役立つ追加のリソースとメソッドにアクセスできます。このクラスは、すべてのProductオブジェクトの固有の特別価格リストに関する情報を格納します。

class PriceList: 

    def __init__(self, name, db_col_name): 
     # Display name 
     self.name = name 

     # Used for querying the database for a specific column 
     # This will always be one of the 4 price related column names 
     # list_price, special_price1, special_price2, or special_price3 
     self.db_col_name = db_col_name 

私は後で各ProductPriceListインスタンスを反復処理を開始します。

for product in products: 
    for price_list in price_lists: 
     # Do stuff 

この時点で私のproductオブジェクトは、新しい特別価格、または私はデータベースに更新する予定の複数の新しい特別価格を持っています。私私のオブジェクトをデータベースセッションに追加してコミットすることができますが、コミットする前に古い価格を取得し、それぞれの価格リストにリンクする必要があります。古い価格は後で私に電子メールで送られるレポートに使われます。私が今やっていることは

for product in products: 
    sku = product.sku 
    for price_list in price_lists: 
     # New price 
     new_price = product.__getattribute__(price_list.db_col_name) 

     # Get the existing special price from the database 
     old_price = s.query(Product.__getattribute__(Product, price_list.db_col_name)).filter(Product.sku.like(sku)).first() 

私は(__getattributeの__を使用してこれを複雑にかけて大幅てるように私は感じる)を下回っています。それは動作しますが、これはpythonicと思われません。更新する前に誰かが未知の列の価値を得る良い方法を知っていますか?データベースの更新は500製品ごとに1回または2回しか行われないため、処理中の外部変数に各特別価格を格納することは効率的ではありません。

+0

なぜ商品オブジェクトをすぐにお持ちの場合は、価格を再取得していますか? – univerio

+0

商品オブジェクトの価格は、その時点までに変更されています。それはデータベースとは異なる新しい価格を持っています。 –

+0

1.フラッシュする前に属性のロードされた値にアクセスできます。あなたができなかったとしても、いつでもあなた自身で属性を保存することができます。 – univerio

答えて

1

属性に動的にアクセスするには、getattr組み込み関数を使用する必要があります。

new_price = getattr(product, price_list.db_col_name) 

インスタンスが古い場合は、次の時間は、あなたが、彼らはデータベースから取得される属性にアクセスすることを意味し、Session.expireを使用する必要があります。

s.expire(product) 

# or only expire price 
s.expire(product, [price_list.db_col_name]) 
+0

あなたの答えをありがとう!私の質問はユニークで混乱していましたが、あなたは私に十分な時間を与えてくれました。 'getattr()'はこのシナリオに使う正しいツールです。 'getattr()'がその属性の** value **を返すので、私はクエリに来ると混乱しました。 's.query(Object.attribute)'を実行しているとき、私はいつも値としてではなくクラスに基づくポインタを考えています...その悪い習慣を壊すことに感謝します。私も知っておいて 'Session.expire'について知りませんでした! –

関連する問題