2012-04-10 26 views
2

あなたは、私は三つのクラスを持って見ることができます記事の下部を見てみると。ここのコードは、飛行機に書かれた擬似コードであり、テストされていませんが、問題を適切に示しています。実際のクラスが必要な場合は、明日の仕事でこの質問を更新できます。構文の問題やコードを無視してください。実際のコードではなく、思考を表現するだけです。SQLAlchemyのアクセス親クラス属性

質問1アイテム検索クラスメソッドを見ると、ユーザーが検索を実行すると、ベースクラスの検索が呼び出され、その結果に基づいて正しいクラス/オブジェクトが返されることがわかります。これは動作しますが、クルージュのようです。これを行うより良い方法はありますか?

質問2 あなたはKitItemクラスを見ればあなたは、私が定価をオーバーライドしていていることがわかります。フラグcalc_listがtrueに設定されている場合、コンポーネントのリスト価格を合計し、その値をキットの定価として返します。真であるとマークされていない場合は、私は "ベース"のリスト価格を返すしたい。しかし、私の知る限りでは、それは無意味が、SQLAlchemyのと、それは役に立つかもしれ共有テーブル継承となり、通常の設定であるため、親の属性にアクセスする方法はありません。

TIA

class Item(DeclarativeBase): 
    __tablename__ = 'items' 
    item_id = Column(Integer,primary_key=True,autoincrement=True) 
    sku = Column(Unicode(50),nullable=False,unique=True) 
    list_price = Column(Float) 
    cost_price = Column(Float) 
    item_type = Column(Unicode(1)) 
    __mapper_args__ = {'polymorphic_on': item_type} 
    __ 
    def __init__(self,sku,list_price,cost_price): 
     self.sku = sku 
     self.list_price = list_price 
     self.cost_price = cost_price 

    @classmethod 
    def search(cls): 
     """ 
     " search based on sku, description, long description 
     " return item as proper class 
     """ 
     item = DBSession.query(cls).filter(...) #do search stuff here 
     if item.item_type == 'K': #Better way to do this??? 
      return DBSession.query(KitItem).get(item.item_id) 

class KitItem(Item): 
    __mapper_args__ = {'polymorphic_identity': 'K'} 
    calc_list = Column(Boolean,nullable=False,default=False) 

    @property 
    def list_price(self): 
     if self.calc_list: 
      list_price = 0.0 
      for comp in self.components: 
       list_price += comp.component.list_price * comp.qty 
      return list_price 
     else: 
      #need help here 
      item = DBSession.query(Item).get(self.item_id) 
      return item.list_price 

class KitComponent(DeclarativeBase): 
    __tablename__ = "kit_components" 
    kit_id = Column(Integer,ForeignKey('items.item_id'),primarykey=True) 
    component_id = Column(Integer,ForeignKey('items.item_id'),primarykey=True) 
    qty = Column(Integer,nullable=False, default=1) 
    kit = relation(KitItem,backref=backref("components")) 
    component = relation(Item) 

答えて

1

回答-1:実際には、あなたはここに特別なことをする必要はありません:あなたは正しく継承階層を構成していることを考えると、あなたのクエリがすでに行ごとに適切なクラスを返します( ItemまたはKitItem)。これはORMの利点です。

@classmethod 
def search(cls): 
    item = DBSession.query(cls).with_polymorphic('*').filter(...) #do search stuff here 
    return item 

:何あなたがが行うことができますすることimmediatellyまた、あなたがwith_polymorphic('*')を指定することによって行うことができますItemの子供(あなたのコードから、これが唯一のcalc_list列です)に属しない追加の列をロードするようにクエリを設定することです詳しくはBasic Control of Which Tables are Queriedを参照してください。
は違い、有効なSQLのログを見て、としてwith_polymorphic(...)せずにテストスクリプトを比較するには - あなたはおそらくSQL文が実行されている以下が必要になります。

Answer-2:純粋に計算されたものに帰属する1つのエントリを上書きしません。代わりに、私はちょうど2つのクラスのそれぞれについて、次のようになり、別の計算された属性(final_priceそれを呼び出すことができます)、作成します。この場合も

class Item(Base): 
    ... 
    @property 
    def total_price(self): 
     return self.list_price 

class KitItem(Item): 
    ... 
    @property 
    def total_price(self): 
     if self.calc_list: 
      _price = 0.0 
      for comp in self.components: 
       _price += comp.component.list_price * comp.qty 
      return _price 
     else: 
      # @note: again, you do not need to perform any query here at all, as *self* is that you need 
      return self.list_price 

を、あなたは熱心にロードする関係KitItem.componentsを設定すると考えるかもしれませんしたがって、total_priceの計算は追加のSQLをトリガーしません。しかし、これがユースケースに有益であるかどうかを自分で判断する必要があります(シナリオで生成されたSQLを分析する)。

+0

おかげであなたの答えは非常に有用でした。 1つの質問は、生成されたSQLを分析するというだけのことですか?文章を印刷して、それを読んで読んでいるかどうか、分析に役立つツールを使っていますか? – Ominus

+0

ちょうどエンジン構成(http://docs.sqlalchemy.org/en/latest/core/engines.html?highlight=echo#engine-creation-api)で#エコー= Trueの#を設定することで、ログ記録SQLステートメントを有効にします – van

関連する問題