3

既存のデータベースがあり、SQLAlchemyを使用してアクセスしたいと考えています。データベース構造は別のコード(実際にはDjango ORM)によって管理されており、すべてのテーブル構造を説明するために繰り返したくないので、autoloadイントロスペクションを使用しています。私は単純な具象テーブルの継承で立ち往生しています。

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

docstringとしてテーブル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、Python2.5.2を使用しています。提案をありがとう。

4

1 に答える 1

4

テーブル構造は、ジョイントテーブル継承で使用されるものと似ていますが、親クラスのすべてのフィールドがサブクラスのテーブルで複製される具体的なテーブル継承には確かに対応していません。現在、親よりもフィールドが少ないサブクラスと、親クラスのインスタンスへの参照があります。共同テーブル継承に切り替えます(そしてFooPayment.amount、条件で使用するか、単純な集約(参照)を優先して継承を放棄します。

他のモデルのフィールドでフィルタリングしても、結合条件は自動的に追加されません。例の結合でどの条件を使用する必要があるかは明らかですが、一般にそのような条件を判別することはできません。そのため、Paymentを参照してリレーションプロパティを定義し、そのhas()メソッドをフィルターで使用して適切な結合条件を取得する必要があります。

于 2009-10-28T09:47:37.337 に答える