SQLAlchemyORM-関係の構築
このセッションでは、データベースにすでに存在するテーブルに関連する別のテーブルの作成について説明します。顧客テーブルには、顧客のマスタデータが含まれています。次に、顧客に属する請求書をいくつでも含めることができる請求書テーブルを作成する必要があります。これは、1対多の関係の場合です。
宣言型を使用して、このテーブルをマップされたクラスである請求書とともに以下のように定義します-
from sqlalchemy import create_engine, ForeignKey, Column, Integer, String
engine = create_engine('sqlite:///sales.db', echo = True)
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
from sqlalchemy.orm import relationship
class Customer(Base):
__tablename__ = 'customers'
id = Column(Integer, primary_key = True)
name = Column(String)
address = Column(String)
email = Column(String)
class Invoice(Base):
__tablename__ = 'invoices'
id = Column(Integer, primary_key = True)
custid = Column(Integer, ForeignKey('customers.id'))
invno = Column(Integer)
amount = Column(Integer)
customer = relationship("Customer", back_populates = "invoices")
Customer.invoices = relationship("Invoice", order_by = Invoice.id, back_populates = "customer")
Base.metadata.create_all(engine)
これにより、CREATETABLEクエリが次のようにSQLiteエンジンに送信されます-
CREATE TABLE invoices (
id INTEGER NOT NULL,
custid INTEGER,
invno INTEGER,
amount INTEGER,
PRIMARY KEY (id),
FOREIGN KEY(custid) REFERENCES customers (id)
)
SQLiteStudioツールを使用して、sales.dbに新しいテーブルが作成されていることを確認できます。
Invoicesクラスは、custid属性にForeignKey構造を適用します。このディレクティブは、この列の値を、customersテーブルのid列に存在する値に制限する必要があることを示します。これはリレーショナルデータベースのコア機能であり、接続されていないテーブルのコレクションを変換して、豊富な重複関係を持つようにする「接着剤」です。
Relationship()と呼ばれる2番目のディレクティブは、属性Invoice.customerを使用してInvoiceクラスをCustomerクラスにリンクする必要があることをORMに通知します。Relationship()は、2つのテーブル間の外部キー関係を使用して、このリンケージの性質を判別し、多対1であると判別します。
追加のrelationship()ディレクティブは、属性Customer.invoicesの下のCustomerマップクラスに配置されます。パラメータrelationship.back_populatesは、補完的な属性名を参照するように割り当てられているため、各relationship()は、逆に表現されたものと同じ関係についてインテリジェントな決定を下すことができます。一方では、Invoices.customerはInvoicesインスタンスを参照し、もう一方では、Customer.invoicesはCustomersインスタンスのリストを参照します。
リレーションシップ関数は、SQLAlchemyORMパッケージのリレーションシップAPIの一部です。これは、2つのマップされたクラス間の関係を提供します。これは、親子または連想テーブルの関係に対応します。
以下は、見つかった基本的な関係パターンです-
1対多
1対多の関係とは、子テーブルの外部キーを使用して親を指します。次に、relationship()は、子によって表されるアイテムのコレクションを参照するものとして、親で指定されます。Relationship.back_populatesパラメーターは、「逆」側が多対1である、1対多の双方向関係を確立するために使用されます。
多対1
一方、多対1の関係では、子を参照するために親テーブルに外部キーが配置されます。Relation()は親で宣言され、新しいスカラー保持属性が作成されます。ここでも、relationship.back_populatesパラメーターが双方向の動作に使用されます。
1対1
1対1の関係は、本質的に双方向の関係です。uselistフラグは、関係の「多」側にコレクションではなくスカラー属性を配置することを示します。1対多を1対1のタイプの関係に変換するには、uselistパラメーターをfalseに設定します。
多対多
多対多の関係は、外部キーを使用して属性を定義することにより、2つのクラスに関連する関連付けテーブルを追加することによって確立されます。これは、relationship()の2次引数によって示されます。通常、テーブルは宣言型基本クラスに関連付けられたMetaDataオブジェクトを使用するため、ForeignKeyディレクティブはリンク先のリモートテーブルを見つけることができます。各relationship()のrelationship.back_populatesパラメーターは、双方向の関係を確立します。関係の両側にはコレクションが含まれています。