2014-09-25 70 views
1

我有一个表(我不允许改变它的模式),它包含三个类表示的行。polymorhpic_on可以用于多个列吗?

ab中的值确定哪一个类对应一行。

if row.a == 'X': return X 
elif row.b == 'Y': return Y 
else: return Z 

显然没有为__polymorhpic_on__好列。有没有办法做到这一点?

+0

如果'row.a =='X'和row.b =='Y''怎么办? X优先于Y吗?我想是的,根据你写的规则,但只是想澄清。 – davidism 2014-09-25 14:34:46

+0

是的,你是对的 – 2014-09-25 14:37:55

回答

2

polymorphic_on可以是列或SQL表达式,所以你只需要找出一个合适的表达式,它将返回一个标识值。

在这种情况下,表达式可以是一个case语句,返回将识别子类的常量。 a == 'X'映射到1,b == 'Y'2等。请注意,该表达式不会返回一个实例,它会生成一个用于映射最终实例的SQL表达式。

case(((a == 'X', 1), (b == 'Y', 2)), else_=3) 

以下是此解决方案的完整运行示例。案例陈述已被修改为使用literal_column s。它更详细,但不需要每次发送4个绑定参数。

import sqlalchemy as sa 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import Session 

engine = sa.create_engine('sqlite://', echo=True) 
session = Session(bind=engine) 
Base = declarative_base(bind=engine) 


class ThreeWay(Base): 
    __tablename__ = 'three_way' 

    id = sa.Column(sa.Integer, primary_key=True) 
    a = sa.Column(sa.String) 
    b = sa.Column(sa.String) 

    __mapper_args__ = { 
     'polymorphic_on': sa.case(
      (
       (a == sa.literal_column("'X'"), sa.literal_column('1')), 
       (b == sa.literal_column("'Y'"), sa.literal_column('2')) 
      ), 
      else_=sa.literal_column('3') 
     ) 
    } 


class X(ThreeWay): 
    __mapper_args__ = { 
     'polymorphic_identity': 1 
    } 

    def __init__(self, **kwargs): 
     kwargs['a'] = 'X' 
     super(X, self).__init__(**kwargs) 


class Y(ThreeWay): 
    __mapper_args__ = { 
     'polymorphic_identity': 2 
    } 

    def __init__(self, **kwargs): 
     kwargs['b'] = 'Y' 
     super(Y, self).__init__(**kwargs) 


class Z(ThreeWay): 
    __mapper_args__ = { 
     'polymorphic_identity': 3 
    } 


Base.metadata.create_all() 

session.add_all((X(), Y(), Z())) 
session.commit() 

print(session.query(ThreeWay).count()) # inserted 3 generic ThreeWay rows 
print(session.query(Y).count()) # 1 of them is specifically a Y row 
+0

表达式必须包含被映射的实例,但是在表达式将被评估的地方没有可用的'self'。表达式中“a”的含义是什么?它似乎是一个列(而不是列值),它肯定不等于'X'。 – 2014-09-25 15:15:15

+0

好吧,我明白了,它非常好用,非常感谢! – 2014-09-25 15:30:24

相关问题