使用SQLAlchemy,我有一个表示表的类。我有一个继承自第一个类的第二个类并覆盖了一些方法。使用哪个类取决于另一个表中的值。我应该如何安排我的代码,以便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
表的类需要根据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)
答案 0 :(得分:1)
Okey 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才能以上述形式工作。