3

我有一个已经存在的数据库,并想使用 SQLAlchemy 访问它。因为,数据库结构由另一段代码(实际上是 Django ORM)管理,我不想重复自己,描述每个表结构,我正在使用autoload自省。我坚持使用简单的具体表继承。

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

这是代码,表 SQL 描述作为文档字符串:

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 内省有效。

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

我正在使用 SQLAlchemy 0.5.3、PostgreSQL 8.3、psycopg2 和 Python 2.5.2。感谢您的任何建议。

4

1 回答 1

4

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

按其他模型中的字段过滤不会自动添加连接条件。尽管对于您的示例,在 join 中应该使用什么条件很明显,但通常无法确定这种条件。这就是为什么您必须定义引用 Payment 的关系属性并has()在过滤器中使用它的方法来获得正确的连接条件。

于 2009-10-28T09:47:37.337 回答