3

查看帖子的底部,您可以看到我有三个课程。这里的代码是动态编写的伪代码,未经测试,但它充分显示了我的问题。如果我们需要实际的课程,我可以在明天工作时更新这个问题。所以忽略语法问题和只代表一个想法的代码,而不是可以做我在那里描述的实际“代码”。

问题 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)
4

1 回答 1

1

答案 1:实际上您不需要在这里做任何特别的事情:假设您正确配置了继承层次结构,您的查询将已经为每一行(ItemKitItem)返回正确的类。这是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:我不会用一个纯粹计算的条目覆盖一个属性。相反,我将只创建另一个计算属性(让我们称之为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)。

于 2012-04-10T13:15:06.097 回答