リレーションシップとJOIN
関連するテーブルをモデル化します
「リレーションシップとJOIN」はCoddyKit上の無料Python Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPython Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Python Academyコースには全4レッスンが含まれています。
関連するテーブル
実際のデータは互いに関連しています。たとえば、1人の著者には複数の本があり、1つの注文には複数の商品があります。SQLAlchemy では、こうしたつながりを リレーションシップ と 外部キー でモデル化します。
# Author 1 --- many --- Book
# A foreign key on Book points back to Author
print('One-to-many is the most common link')外部キー
外部キー カラムには、関連する行の主キーが格納されます。ForeignKey('table.column') を使って宣言します。
from sqlalchemy import ForeignKey
from sqlalchemy.orm import Mapped, mapped_column
# author_id: Mapped[int] = mapped_column(ForeignKey('authors.id'))
print('ForeignKey links child to parent')親の定義
親モデルでは、relationship() を使って子のコレクションを保持します。
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
from typing import List
class Base(DeclarativeBase):
pass
class Author(Base):
__tablename__ = 'authors'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
books: Mapped[List['Book']] = relationship(back_populates='author')
print('Author.books holds related Book objects')子の定義
子モデルには、外部キーカラムと、親を参照する relationship() が含まれます。
from sqlalchemy import ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
class Base(DeclarativeBase):
pass
class Book(Base):
__tablename__ = 'books'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
author_id: Mapped[int] = mapped_column(ForeignKey('authors.id'))
author: Mapped['Author'] = relationship(back_populates='books')
print('Book.author points to its parent')back_populates
back_populates は2つのリレーションシップを関連付け、一方を更新するともう一方にも自動的に反映されるようにします。
# author.books.append(book) also sets book.author = author
# Both sides stay in sync automatically
print('back_populates keeps both sides consistent')リレーションシップの利用
関連付けると、通常の属性と同じようにリレーションシップをたどれます。author.books はリストで、book.author は親オブジェクトです。
# for book in author.books:
# print(book.title)
# print(book.author.name)
print('Navigate with plain attribute access')グラフの構築
親のコレクションに子を追加します。親を Session に追加すると、子にもカスケードされます。
# a = Author(name='Rowling')
# a.books.append(Book(title='Book 1'))
# session.add(a)
# session.commit() # author and book both saved
print('Cascade saves the whole object graph')暗黙的な JOIN
book.author にアクセスすると、SQLAlchemy は関連する行を自動的に読み込みます。これは内部で行われる遅延ロードです。
# Accessing book.author runs a SELECT if not loaded yet
# This is lazy loading
print('Lazy loading fetches related rows on access')明示的な JOIN
テーブルをまたいでフィルタリングするには、select の中で join() を使用します。これにより SQL JOIN が生成されます。
from sqlalchemy import select
# stmt = select(Book).join(Author).where(Author.name == 'Rowling')
# books = session.scalars(stmt).all()
print('join(Author) filters across the relationship')先行ロード
小さなクエリが大量に発行されるのを避けるには、joinedload または selectinload を使って関連する行をあらかじめ読み込みます。
from sqlalchemy import select
from sqlalchemy.orm import selectinload
# stmt = select(Author).options(selectinload(Author.books))
print('selectinload preloads children in one extra query')多対多の関連
多対多の関連では、関連付けテーブルが両側をつなぎます。relationship() の secondary= でそのテーブルを指定します。
# students <-> courses via a 'enrollments' association table
# courses: Mapped[List['Course']] = relationship(secondary=enrollments)
print('secondary= models many-to-many')理解度チェック
リレーションシップに関する知識を確認しましょう。
まとめ
関連するテーブルをモデル化しました。
ForeignKeyは子のカラムにリンクを格納しますrelationship()とback_populatesで両側を接続します- リンクを通常の属性としてたどり、遅延ロードによってアクセス時に取得します
join()はテーブルをまたいだフィルタリングに使い、selectinloadは先行ロードを行い、secondary=は多対多の関連を処理します
よくある質問
「リレーションシップとJOIN」レッスンは無料ですか?
はい。「リレーションシップとJOIN」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Python Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Python Academyコースには全4レッスンが含まれています。
「リレーションシップとJOIN」で何を学びますか?
関連するテーブルをモデル化します ブラウザで直接実行するハンズオンコードでPython Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Python Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのPython Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「リレーションシップとJOIN」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このPython Academyレッスンでコードを書いて実行できますか?
はい。すべてのPython Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- SQLAlchemy CoreとORMの違い
- モデルの定義
- Sessionによるクエリ
- リレーションシップとJOIN