inheritance - 在 Sqlalchemy的字段值上,实例化父类或者子类

  显示原文与译文双语对照的内容
81 0

使用 Sqlalchemy,我有一个表示 table的类。 我有第二个继承自第一个类并重写一些方法的类。 要使用的类取决于另一个 table 中的值。 如何安排代码,以便 Sqlalchemy 在执行查询时为我创建正确的类,或者访问关系属性。

我的代码看起来像这样:


class Thing(Base): 
. . . 
 relevant_property = Column(Bool) 


class RelatedThing(Base): # Should be used if self.thing.relevant_property is True 
. . . 
 thing = relationship("Thing") 
 def do_stuff(self): 
 return 1 


class RelatedThingChild(RelatedThing): # Should be used if self.thing.relevant_property is False 
 def do_stuff(self): 
 return 2 


class SomethingDifferent(Base): 
. . . 
 related_thing = relationship("RelatedThing") # Plugging in"RelatedThing" here probably isn't right, but I don't know what is 


def get_related_things(): 
 # This function doesn't know which version of RelatedThing it wants. Might even want a mix of both. 
 return DBSession.query(RelatedThing).all() # Plugging in"RelatedThing" here probably isn't right, but I don't know what is 


def use_something_different(sd): 
 sd.related_thing.do_stuff() # Needs sd.related_thing to be the right class.


更新: 这是有关相关表的实际数据库模式。 表示 tests table的类需要基于 series.regression 进行更改。


pdiff=# dS series
 Table"public.series"
 Column | Type | Modifiers 
----------------+-----------------------------+------------------------------------------------------------
 series_id | integer | not null default nextval('series_series_id_seq'::regclass)
 name | text | 
 control_domain | text | 
 test_domain | text | 
 created | timestamp without time zone | default now()
 reload_url | text | 
 regression | boolean | 
Indexes:
"series_pkey" PRIMARY KEY, btree (series_id)
Referenced by:
 TABLE"tests" CONSTRAINT"tests_series_id_fkey" FOREIGN KEY (series_id) REFERENCES series(series_id)
 TABLE"urls" CONSTRAINT"urls_series_id_fkey" FOREIGN KEY (series_id) REFERENCES series(series_id)

pdiff=# dS tests
 Table"public.tests"
 Column | Type | Modifiers 
-----------+-----------------------------+---------------------------------------------------------
 test_id | integer | not null default nextval('tests_test_id_seq'::regclass)
 series_id | integer | 
 created | timestamp without time zone | default now()
 status | text | 
Indexes:
"tests_pkey" PRIMARY KEY, btree (test_id)
Check constraints:
"status_check" CHECK (status = ANY (ARRAY['complete'::text, 'running'::text, 'queued'::text, 'failed'::text]))
Foreign-key constraints:
"tests_series_id_fkey" FOREIGN KEY (series_id) REFERENCES series(series_id)
Referenced by:
 TABLE"engine_tests" CONSTRAINT"diffs_test_id_fkey" FOREIGN KEY (test_id) REFERENCES tests(test_id)
 TABLE"urls_tests" CONSTRAINT"urls_tests_test_id_fkey" FOREIGN KEY (test_id) REFERENCES tests(test_id)

时间: 原作者:

79 2

好的,doke,只是一个布尔值,数据驱动( 比如 。 它不像一个固定的下拉值或者什么的固定表。 所以我们称为标识符的列将是一个标量( 单行/行) 选择,从"系列"表中从"回归"中拉出。 有几种配置可以布局,下面我们只在定义两个类之后设置鉴别器:


from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Series(Base):
 __tablename__ = 'series'

 id = Column(Integer, primary_key=True)
 regression = Column(Boolean)

class Test(Base):
 __tablename__ = 'test'

 id = Column(Integer, primary_key=True)
 series_id = Column(Integer, ForeignKey('series.id'))

 series = relationship("Series")

 __mapper_args__ = {
"polymorphic_identity": False,
 }

Test.is_regression = column_property(
 select([
 Series.regression
 ]).
 where(Test.series).as_scalar()
 )
Test.polymorphic_on = Test.is_regression

class RegressionTest(Test):
 __mapper_args__ = {"polymorphic_identity": True}

e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)

sess = Session(e)

s1, s2, s3 = Series(regression=True), Series(regression=False), 
 Series(regression=True)
sess.add_all([
 Test(series=s1),
 Test(series=s2),
 Test(series=s2),
 Test(series=s3),
 Test(series=s1),
 Test(series=s2),
])
sess.commit()
sess.close() # clears out the Session since we're going to reload with specific classes

for t in sess.query(Test).order_by(Test.id):
 print(t, t.is_regression)

这里脚本至少需要 Sqlalchemy 0.8才能在上面的表单中工作。

原作者:
...