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

我已经有一个数据库,想使用SQLAlchemy访问它.因为数据库结构是由另一段代码(实际上是Django ORM)管理的,并且我不想重复描述每个表结构,所以我使用的是自动加载内省.我坚持使用简单的具体表继承.

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没有在实例级别实现属性u’date’.

我尝试将隐式外键引用id = Column(‘payment_ptr_id’,Integer,ForeignKey(‘payments_payment.id’),primary_key = True)添加到FooPayment没有任何成功.尝试打印session.query(Payment).first().user可以完美地工作(我省略了User类,并注释了该行),因此FK自省工作了.

如何在FooPayment上执行简单查询并从结果实例访问Payment的值?

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

解决方法:

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

在其他模型中按字段过滤不会自动添加联接条件.尽管很明显,在示例中应在连接中使用什么条件,但通常无法确定这种条件.因此,您必须定义引用Payment的关系属性,并在过滤器中使用其has()方法来获取适当的加入条件.

上一篇:理解SQLAlchemy的表继承关系(3)-Concrete Table Inheritance


下一篇:caement Archaic spelling of cement