2013-05-06 51 views
0

我有一对看起来有点像这样(简化的示例)的PostgreSQL表:从people用SQLAlchemy对这种类型的继承进行建模的正确方法是什么?

CREATE TABLE people (
    id SERIAL PRIMARY KEY, 
    created timestamp with time zone DEFAULT now() NOT NULL, 
    modified timestamp with time zone NULL, 
    email varchar NOT NULL UNIQUE, 
    inactive boolean NOT NULL DEFAULT False 
); 

CREATE TABLE engineers (
    id integer NOT NULL REFERENCES people(id) ON DELETE CASCADE ON UPDATE CASCADE UNIQUE, 
    created timestamp with time zone DEFAULT now() NOT NULL, 
    modified timestamp with time zone NULL, 
    login_name varchar NOT NULL UNIQUE, 
    PRIMARY KEY(id) 
); 

engineers继承因为“ID”列people穿过到engineers作为外键。该列也被定义为两个表中的主键。如果我想查询LOGIN_NAME使用某人的电子邮件地址,就可以像这样通过SQL完成:

SELECT p.email FROM engineers e 
    JOIN people p ON p.id = e.id 
    WHERE p.inactive = False AND e.login_name = 'john.smith'; 

如何使用模型SQLAlchemy的的声明式的这种关系,并执行类似的查询?看起来像“Joined Table Inheritance”描述了我的使用场景,但我的表中没有鉴别器列。我也一直在尝试使用“Concrete Table Inheritance”,但我只是想迷惑自己。

我会很感激任何建议。谢谢!

编辑

的原因,这表结构是现在这个样子是因为“人”可能是一个“工程师”,“会计”,或“测试”(或三者的某种组合)。该people表包含共同的每一个人的属性,诸如姓名,电话,数字,租赁日期等

“创建”和在engineerspeople之间不共享“修饰的”列;这两列对每个表都是不同的。这些不是绝对必要的,它们只是默认添加到数据库中的每个表定义中,并用于跟踪用于审计/日志记录目的的更改。

回答

0

你在这里有什么不明确的类型,因为你重复一些列而不是其他人。

docs

SQLAlchemy的支持三种形式的继承:单表继承,其中多种类型的类由一个单一的表来表示,混凝土表继承,每种类型的类别的其中由独立表格表示,并且联合表格继承,其中类别层次结构在相关表格之间分解,每个类别由其自己的表格表示,该表格仅包括那些类别的本地属性。

由于您复制了createdmodified列,因此这是具体继承的候选项。但是,因为您预期Employee是一个不完整的实体,没有来自Person的列,所以这也是连接表的继承。

我建议你尝试使这适合连接表继承,但我不完全确定该映射器将如何处理重复列的存在。在连接表继承中,可以将子类分别作为关系进行操作,但是我不确定如何合并它们,如果它们可以合并,或者可以使用哪种映射器配置来处理使用哪个子类。如果有办法,this section可能会告诉你如何。

但是,这是让你开始的东西。polymorphic_on can also be any sql expression (scroll down to the polymorphic_on argument) - 它不一定是一列。如果唯一的子类是engineers表,则可以在鉴别器中使用EXISTS子查询。

下面是一些未经测试的代码,如果不对它进行一些修改,它可能无法正常工作 - 它只是向您显示您将不得不使用的模式。

people_table = Table('people', metadata, 
    Column('id', Integer, primary_key=True), 
    Column('email', String, unique=True), 
    Column('inactive', Boolean, default=False), 
) 

engineers_table = Table('engineers', metadata, 
    Column('id', Integer, ForeignKey('people.id'), primary_key=True), 
    Column('engineer_info', String), 
) 

class Person(object): 
    pass 

class Engineer(Person): 
    pass 


discriminator = case(
    [ 
     (exists().where(people_table.c.id==engineers_table.c.id), 'engineer'), 
    ], else_='person') 

mapper(Person, people_table, polymorphic_identity='person', polymorphic_on=discriminator) 
mapper(Engineer, engineer_table, polymorphic_identity='engineer') 

不用说,如果这是在所有可能你应该,你自己的理智:

  1. 添加一个鉴别列到你的person表。
  2. 摆脱engineer表中的createdmodified列。
+0

哇。感谢您的详细回复。我编辑了这个问题来解决点#1和#2。明天早上我会花更多的时间用你的例子。 – jamieb 2013-05-06 05:15:52

相关问题