1

SQLAlchemy モデルの構成に関して全体像をつかむのを手伝ってくれる人がいるので、すべてのレベルで参照整合性が保証されますか?

参照整合性は DB によって表現および強制されるべきであるという考えに基づいて、必要と思われるすべての制約を備えたスキーマ (現在は Postgresql 内) を作成しました。

次に、宣言モードで SQLAlchemy (0.7) を使用して、この DB の上にアプリを構築し始めます。

少し検索して読んだところ、次のように構成できることがわかりました。

  • Column() 定義の onupdate/ondelete ルール。
  • relationship() 定義のカスケード オプション、
    およびこれらが SQLAlchemy のセッション レベルで動作するように見えること。
  • relationship() 定義の passive_deletes および passive_updates オプション。

そして、これらすべてのオプションにはデフォルトがあります。

しかし、セッション中に SQLAlchemy が DB とその制約と同期しなくなることがないように、SQLAlchemy モデルを実際にどれだけ処理する必要があるかについて、私は混乱しています。

SQLAlchemy の Columns() 定義で「onupdate」などを構成すると、正確には何を達成できますか?

また、cascade および passive_delete/passive_update ルールについては、relationship() で構成できます。ここで必要なものとその理由

または、私の質問を言い換えると: SQLAlchemy は、DB スキーマで構成された制約をどの程度まで認識し、モデルでそれらをどの程度 (およびどのように) 繰り返す必要がありますか?

他に注意すべきことはありますか?:)

4

2 に答える 2

4

SQLAlchemy は基本的に、データベースの制約について何も知る必要はありません。データベースに必要な制約が設定されている場合、基本的には完了です。アプリケーションは、想定されていないことをデータベースが実行することを許可されていません。

SQLAlchemy の重要なテーマは、実際には指示されたことだけを実行するということです。そのため、SQLAlchemy がデータをフラッシュする (つまり、INSERT ステートメントを発行する) 時点で、データベース内で親 Widget() への参照が必要なオブジェクト SubWidget() を永続化しようとすると、操作は失敗します。データベースによって発行された制約違反で、トランザクションはロールバックされます。

したがって、「ウィジェット」を参照する「サブウィジェット」の FK を想定すると、アプリケーションはデータが正しい構造であることを確認する必要があります。これには 2 つの方法があります。1 つは、外部キー参照を含む列を手作業で維持し、INSERT または UPDATE の時点で適切な値を保持していることを確認することです。もう 1 つはrelationship()、外部キー属性を管理するために使用し、代わりに SubWidget() オブジェクトの作成に、それを作成した親 Widget() オブジェクトに関連付ける操作が伴うことを確認することです。および/または個別に取得します。

カスケードに関しては、必須ではありませんが、適用される外部キーに ON DELETE CASCADE を設定することをお勧めします。SQLAlchemy 側では、relationship()通常、データベースが passive_deletes フラグ ( http://www.sqlalchemy.org/docs/orm/collections.html?highlight=passive_deletes#using -passive-deletes )、ただし、これは通常、パフォーマンスの向上です。それ以外の場合、SQLAlchemy は、 の依存側で表されるすべてのオブジェクトrelationship()がメモリにロードされ、適切に処理されることを保証します。これは、外部キー属性を NULL に設定する (デフォルト) か、依存オブジェクトに削除のマークを付ける (これは、 「cascade」を「all, delete-orphan」に設定します。http://www.sqlalchemy.org/docs/orm/session.html#cascades )。

ON UPDATE カスケードはあまり一般的ではありません。自然な主キーは、実際にはプレーンな整数の主キーと同じように機能せず、他の方法でも扱いにくいため、最近では一般的な方法ではありません。ただし、SQLAlchemy はこれらもサポートしており、通常は SQLA が PK ミューテーションが発生したときに更新カスケードが行われていると想定しているため、通常は自動処理されます。http://www.sqlalchemy.org/docs/orm/relationships を参照してください。詳細な説明については、.html#mutable-primary-keys-update-cascadesを参照してください。

おそらく、これは少し実験するだけで簡単に理解できます。基本的な考え方は、SQLAlchemy の SQL 動作の多くは事前に設定すると自動化されますが、SQLAlchemy は指定した SQL のみを発行するということです。 relationship()データベースに存在する制約に関して、データが永続化、変更、または削除されたときにどのように動作するかについての詳細を使用して構成する必要があります。

于 2011-09-29T22:24:31.790 に答える
1

それで、zzzeeksの答えに基づいて構築し、最初の質問の後に私自身の勉強/いじくり回し...

SQLAlchemyが、DB 状態のセッション内ビューが、フラッシュ/コミット時に DB が許可するものから逸脱することを積極的に防止するには、SQLAlchemy モデルの DB スキーマで見つかったすべての制約をミラーリングする必要があります。

これは、次の形式の列定義を介して行われます。

ForeignKey(..., onupdate='', ondelete='')
primary_key=True
unique=True

以下のように、__table_args__ を含めることもできます。

__table_args__ = (
        ForeignKeyConstraint(['id'], ['remote_table.id']),
        UniqueConstraint('foo'),
        )

制約が複数の列にまたがる場合。

一方:

relationship()

およびその関連する引数は次のとおりです。

cascade
cascade_backrefs
foreign_keys
passive_deletes
passive_updates

などは、可能な限り少ない労力でモデルを操作できるようにする (重要な) 便利な機能ですが、最終的には参照整合性の違反を防ぐことを意図したものではありません。

Relationship() 機能は、データベース内のすべての典型的な制約を表現することはできませんが、Column() (および __table_args__) 機能は表現できます。

一方、上記の引数のいくつかを使用して relationship() を構成すると (または、それが最も理にかなっている場合はデフォルト値を使用して)、SQLAlchemy が自動的にタスクを実行できるようになります。これは、最終的に参照整数関連と言えます。それ以外の場合は、通常、周囲のコードのロジックで表現する必要があります。

Relationship() の最適な構成は、場合によっては、SQLAlchemy によって不要な SQL ステートメントが発行されるのを回避します。

この合計がある程度正確であることを願っています...

于 2011-09-30T13:04:47.960 に答える