代码之家  ›  专栏  ›  技术社区  ›  drdaeman

SQLAlchemy声明性具体的自动加载表继承

  •  3
  • drdaeman  · 技术社区  · 15 年前

    我已经有一个数据库,希望使用sqlacalchemy访问它。因为,数据库结构是由另一段代码(实际上是django-orm)管理的,我不想重复,描述我正在使用的每个表结构 autoload 反省。我只能继承一个简单的具体表。

    Payment                FooPayment
      + id (PK) <----FK------+ payment_ptr_id (PK)
      + user_id              + foo
      + amount
      + date
    

    下面是代码,表SQL描述为docstrings:

    class Payment(Base):
        """
        CREATE TABLE payments(
          id serial NOT NULL,
          user_id integer NOT NULL,
          amount numeric(11,2) NOT NULL,
          date timestamp with time zone NOT NULL,
          CONSTRAINT payment_pkey PRIMARY KEY (id),
          CONSTRAINT payment_user_id_fkey FOREIGN KEY (user_id)
              REFERENCES users (id) MATCH SIMPLE)
        """
        __tablename__ = 'payments'
        __table_args__ = {'autoload': True}
        # user = relation(User)
    
    class FooPayment(Payment):
        """
        CREATE TABLE payments_foo(
          payment_ptr_id integer NOT NULL,
          foo integer NOT NULL,
          CONSTRAINT payments_foo_pkey PRIMARY KEY (payment_ptr_id),
          CONSTRAINT payments_foo_payment_ptr_id_fkey
              FOREIGN KEY (payment_ptr_id)
              REFERENCES payments (id) MATCH SIMPLE)
        """
        __tablename__ = 'payments_foo'
        __table_args__ = {'autoload': True}
        __mapper_args__ = {'concrete': True}
    

    实际的表有额外的列,但这与问题完全无关,因此为了尽量减少代码,我已经将所有内容简化到核心。

    问题是,当我运行此命令时:

    payment = session.query(FooPayment).filter(Payment.amount >= 200.0).first()
    print payment.date
    

    结果SQL毫无意义(请注意,缺少连接条件):

    SELECT payments_foo.payment_ptr_id AS payments_foo_payment_ptr_id,
           ... /* More `payments_foo' columns and NO columns from `payments' */
        FROM payments_foo, payments
        WHERE payments.amount >= 200.0 LIMIT 1 OFFSET 0
    

    当我试图进入 payment.date 我得到以下错误: Concrete Mapper|FooPayment|payments_foo does not implement attribute u'date' at the instance level.

    我尝试添加隐式外键引用 id = Column('payment_ptr_id', Integer, ForeignKey('payments_payment.id'), primary_key=True) FooPayment 没有任何成功。尝试 print session.query(Payment).first().user 工作(我省略了 User 课堂和评论的话)完美,所以FK反思工作。

    如何执行简单查询 诱骗 和访问 Payment 结果实例的值?

    我使用的是sqlacalchemy 0.5.3、postgresql 8.3、psycopg2和python 2.5.2。 谢谢你的建议。

    1 回复  |  直到 15 年前
        1
  •  4
  •   Denis Otkidach    15 年前

    您的表结构与联合表继承中使用的结构类似,但它们肯定与具体的表继承不对应,其中父类的所有字段都在子类的表中重复。现在您有了一个子类,它的字段比父类少,并且引用了父类的实例。切换到联合表继承(并使用 FooPayment.amount 在您的条件下,或者放弃继承而选择简单的聚合(引用)。

    按其他模型中的字段筛选不会自动添加联接条件。尽管对于您的示例来说,在join中应该使用什么条件是显而易见的,但是一般来说,不可能确定这样的条件。这就是为什么您必须定义与付款相关的关系属性,并使用它 has() 方法以获得正确的联接条件。