前回、SELECT 〜 JOIN をやってみたが、期待通りのことが出来なかった。 少し調べたら、やり方がわかったのでまとめておく。
selectメソッドに対象のモデルを指定する
selectメソッドで検索時に取得するデータのモデルを指定して、executeメソッドを実行するだけ。
scalarsメソッドは特定のカラムの値を抽出するために使用するため、scalarsメソッドでデータ取得するとStudent
テーブルのデータが取得できない。
executeメソッドは、全体の結果を取得するため、結合して取得したデータに対して、対応するモデルに値を設定してくれる。
stmt = select(School, Student).join(School, Student.school_id == School.id) results = session.execute(stmt)
値の参照方法
以下のように、Rowインスタンスにモデルクラス.変数名
でアクセスできる。
Studentテーブルのnameカラムの値を取得したい場合、Rowインスタンスの変数名.Student.name
で取得する。
print("student.id = " + str(result.Student.id)) print("student.name = " + str(result.Student.name)) print("student.school.name = " + str(result.School.name))
最後に
SQLAlchemyのマニュアルに複数のORMエンティティを使用する場合について記載されていた。やりたいことがマニュアルに書かれていたので、改めてマニュアルを確認することは大事だと気付かされた。
参考
ソース
from sqlalchemy import create_engine from sqlalchemy.types import Integer, String from sqlalchemy.orm import DeclarativeBase from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import relationship from sqlalchemy import ForeignKey from sqlalchemy import select class Base(DeclarativeBase): pass class Student(Base): __tablename__ = "student" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(String(30)) school_id: Mapped[int] = mapped_column(ForeignKey("school.id")) class School(Base): __tablename__ = "school" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(String(30)) # DBエンジンを作成 url = "postgresql://postgres:example@localhost:5432/postgres" engine = create_engine(url, echo=True) # テーブルをDBに作成 Base.metadata.create_all(engine) # セッションを作成 # セッションを介してクエリを実行する SessionClass = sessionmaker(engine) session = SessionClass() school1 = School(name="あいうえお学園") school2 = School(name="かきくけこ学園") school3 = School(name="さしすせそ学校") session.add_all([school1, school2, school3]) session.commit() student1 = Student(name="sato", school_id=1) student2 = Student(name="tanaka", school_id=2) student3 = Student(name="watanabe", school_id=3) session.add_all([student1, student2, student3]) session.commit() stmt = select(School, Student).join(School, Student.school_id == School.id) # results = session.scalars(stmt) results = session.execute(stmt) for result in results: print("student.id = " + str(result.Student.id)) print("student.name = " + str(result.Student.name)) print("student.school.name = " + str(result.School.name))
version: "3.1" services: db: image: postgres restart: always environment: POSTGRES_PASSWORD: example ports: - 5432:5432 adminer: image: adminer restart: always ports: - 8080:8080