3

投稿の下部を見ると、3つのクラスがあることがわかります。ここでのコードは、その場で記述され、テストされていない擬似コードですが、私の問題を適切に示しています。実際のクラスが必要な場合は、明日仕事中にこの質問を更新できます。したがって、構文の問題と、そこで説明することを実行する実際の「コード」ではなく、思考のみを表すコードは無視してください。

質問1Itemsearchクラスのメソッドを見ると、ユーザーが検索を実行すると、基本クラスでsearchを呼び出し、その結果に基づいて正しいクラス/オブジェクトが返されることがわかります。これは機能しますが、扱いにくいようです。これを行うためのより良い方法はありますか?

質問2KitItemクラスを見ると、私が定価を上書きしていることがわかります。フラグcalc_listがtrueに設定されている場合、コンポーネントの定価を合計し、それをキットの定価として返します。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)
4

1 に答える 1

1

回答-1:実際、ここで特別なことをする必要はありません。継承階層を適切に構成した場合、クエリはすべての行(ItemまたはKitItem)に対して適切なクラスを既に返します。これがORMパーツの利点です。Itemただし、次のように指定することで、 (コードからはこれはcalc_list列のみです)の子に属する追加の列もすぐにロードするようにクエリを構成することができますwith_polymorphic('*')

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

詳細については、クエリを実行するテーブルの基本制御を参照してください。
違いを確認し、SQLロギングを有効にして、テストスクリプトを使用する場合と使用しないwith_polymorphic(...)場合を比較します。おそらく、SQL実行するステートメントが少なくて済みます。

回答-2:純粋に計算されたものに起因する1つのエントリを上書きしません。代わりに、別の計算属性を作成します(これを呼び出しますfinal_price)。これは、2つのクラスのそれぞれについて次のようになります。

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

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

于 2012-04-10T13:15:06.097 に答える