【问题标题】:Inherit From SQLAlchemy Joined Table Inheritance Class从 SQLAlchemy 连接表继承类继承
【发布时间】:2018-03-04 12:05:10
【问题描述】:

Python 3.6 和 SQLAlchemy 1.2。

我有一个名为events 的包,它将Match 定义为Event 的一种类型,并使用连接表继承将其与其他类型的Event 区分开来。另一种类型的事件是Competition,所有事件都是其中之一:

class Event(Base):
    __tablename__ = 'tbl_events'
    event_id = Column(Integer, primary_key=True)
    event_type_id = Column(String(50))  # 0 is Match, 1 is Competition

    __mapper_args__ = {'polymorphic_on': event_type_id}

class Match(Event):
    __tablename__ = 'tbl_match_details'

    event_id = Column(Integer,
                      ForeignKey('tbl_events.event_id'),
                      primary_key=True)
    team_1 = Column(String(50))
    team_2 = Column(String(50))

    __mapper_args__ = {'polymorphic_identity': 0}

我在另一个包中使用Match,它区分多种类型的Match,并依赖Match对象的属性和方法从数据库中提取事件信息,但在远离数据库的情况下操作:

from events import Match

class BaseMatch(Match):
    # define common methods and attrs

class TennisMatch(BaseMatch):

    # do Tennis based stuff

class FootballMatch(BaseMatch):

    # do football based things

events.Match 和从它继承的类之间的任何区别仅在此包中很重要,并且此包不会插入或更新数据库,只会从中读取。

我遇到的问题是,尝试实例化从Match 继承的任何类的实例会导致NULL 值被传递到event_type_id 字段的查询中。这是查询的WHERE 部分:

WHERE tbl_match_details.event_id = %s AND tbl_events.match_comp_id IN (NULL)

我不能简单地给每个类自己的多态标识符,因为这些标识符不会存在于数据库中。

我试过这个:

class BaseMatch(Match):
    @declared_attr
    def __mapper_args__(cls):
        return {'polymorphic_identity': 0}

class TennisMatch(BaseMatch):
    # do tennis stuff

class FootballMatch(BaseMatch):
    # do footy stuff

但导入模块时,我收到如下警告:

SAWarning: Reassigning polymorphic association for identity 0 from <Mapper at 0x7f80197f0550; Match> to <Mapper at 0x7f80197a9fd0; BaseModel>: Check for duplicate use of 0 as value for polymorphic_identity.
SAWarning: Reassigning polymorphic association for identity 0 from <Mapper at 0x7f80197a9fd0; BaseModel> to <Mapper at 0x7f800dfdf940; TennisMatch>: Check for duplicate use of 0 as value for polymorphic_identity.

我为从Match 继承的每个类获取其中一个,当我尝试实例化任何匹配类型时,我得到最后一个与该多态 id 关联的类型的实例。

我真的很感激朝着正确的方向轻推!

谢谢。

【问题讨论】:

    标签: python python-3.x orm sqlalchemy


    【解决方案1】:

    这是我为解决这个问题所做的工作 - 我不确定它是否“正确”,但它让我能够继续我正在做的事情,并帮助我了解更多的事情在引擎盖下。

    我在 Event、Competition 和 Match 类上创建了一个工厂方法,并在 Competition 和 Match 上创建了一个类属性,让我可以访问每个事件类型的 event_type_id 值:

    from sqlalchemy import inspect
    
    class Event(Base):
        __tablename__ = 'tbl_events'
        event_id = Column(Integer, primary_key=True)
        event_type_id = Column(String(50))  # 0 is Match, 1 is Competition
    
        __mapper_args__ = {'polymorphic_on': event_type_id}
    
        @classmethod
        def from_id(cls, id, session):
            mapper = inspect(cls).mapper
            mapper.polymorphic_map[cls.EVENT_TYPE_ID] = mapper
            mapper.polymorphic_identity = cls.EVENT_TYPE_ID
    
            return session.query(cls).filter_by(event_id=id).one()
    
    class Match(Event):
    
        EVENT_TYPE_ID = 0
    
        __tablename__ = 'tbl_match_details'
    
        event_id = Column(Integer,
                          ForeignKey('tbl_events.event_id'),
                          primary_key=True)
        team_1 = Column(String(50))
        team_2 = Column(String(50))
    
        __mapper_args__ = {'polymorphic_identity': EVENT_TYPE_ID}
    

    这样,每当使用工厂方法实例化从 Match 或 Competition 继承的类时,多态标识被强制为父类上定义的标识,并且多态映射将该标识指向调用工厂的类上。

    对我来说明显的一个缺点是,这仅在通过工厂方法实例化对象时才有效。在这种情况下很好,但可能并不适用。

    对于我如何处理此问题的任何反馈以及任何指向更清洁解决方案的建议,我们将不胜感激。

    谢谢

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-16
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-06
      • 2023-03-27
      相关资源
      最近更新 更多