FastAPIを使ってPostgreSQLへ接続するのは、初めてですので下記のサイトを参考にさせていただきました。
FastAPIとPostgreSQLの結合:モデル定義とマイグレーション入門
Backend側(DastAPI)のディレクトリ構成
1.モジュールのインストール
pydantic-settingsのインストール
pydantic-settingsは、Pydanticライブラリの拡張機能で、環境変数や.envファイルなどの設定を型安全に読み込み、管理するためのツールです。これにより、設定値のバリデーション(検証)や型変換が自動的に行われ、安全で保守しやすい設定管理を実現します。通常はosモジュールで行うような環境変数管理を、クラスベースで簡潔かつ型チェックも同時に行うことができます。
このモジュールを下記のコマンド使ってインストールしましょう。
pipenv install pydantic-settings
psycopg2-binaryのインストール
psycopg2-binaryは、PythonからPostgreSQLデータベースに接続するためのライブラリ psycopg2 の、コンパイル済みのバイナリパッケージです。
下記のコマンドを使ってインストールしましょう。
pipenv install psycopg2-binary
SQLAlchemyのインストール
SQLAlchemyとは、Pythonでデータベースを操作するためのライブラリです。
下記のコマンドを使ってインストールしましょう。
pipenv install SQLAlchemy
Pydanticのインストール
Pydantic公式サイト
Pydanticのインストール
下記のコマンド使ってインストールします。
pipenv install pydantic
pipenv install pydantic-settings
2.appフォルダを新規作成
backendフォルダの直下にappフォルダを作成しましょう。
つぎに、__init__.pyファイルを作成します。このファイルは、「Pythonにこのディレクトリをパッケージとして認識させるために必要なファイル」です。
__init__.pyファイルの中身は、空のファイルで大丈夫です。
3.Modelの作成とORMを設定
ここでは、FastAPIとPiostgreSQLを接続する他のデータ情報を設定します。
前述で作成したappフォルダ配下にdbフォルダを作成します。
ここで作成したBaseクラスは、他のモデルクラスが継承する基底クラスです。
そのため、このクラスを継承することで、下記の利点が得られます。
1.作成するモデルクラスはSQLAlchemyの機能にアクセスできる。
2.データベースとのインタラクションが可能となる。
3.__tablename__メソッドを利用して、継承したクラスのインスタンスがデータベースにマッピングされる際のテーブル名を自動生成できる。
3-1.base_class.pyの作成
from typing import Any
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.orm import as_declarative
@as_declarative()
class Base:
id: Any
__name__: str
# Generate __tablename__ automatically
@declared_attr
def __tablename__(cls) -> str:
return cls.__name__.lower()
4.ユーザー(User)モデルの作成
つぎに、appフォルダ配下にmodelsフォルダを作成します。
modelsフォルダの配下に前掲の基底クラス(base_class.pyを継承した)user.pyを作成します。
このファイルをマイグレーションすると、ORM機能によりPostgreSQLにモデル情報が反映されます。
from datetime import datetime
from app.db.base_class import Base
from sqlalchemy import Column, DateTime, String
class User(Base):
__tablename__ = "users"
id = Column(String, primary_key=True)
name = Column(String(20), nullable=False, default="default_name")
created_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
5.FastAPIとPostgreSQLの接続設定
前掲の「1.モジュールのインストール」で下記のモジュールをインストールしたのでここでは、インストール捜査は不要です。
5-1. 設定ファイルの作成
appディレクトリの中にcoreディレクトリを新規作成します。
配下に__init__.pyとconfig.pyという名前のファイルを作成しましょう。
__init__.pyは空のファイルで大丈夫です。__init__.pyを配置することで、Pythonはこのディレクトリをパッケージとして認識します。
5-2.config.pyを更新
config.pyには、pydantic-settingsのBaseSettingsクラスを利用します。
このBaseSettingsクラスを利用することで、環境変数や.envファイルからの設定値を簡単に読み込むことができるようになります。
import enum
from typing import Any,Optional
from pydantic import PostgresDsn,ValidationInfo,field_validator
from pydantic_settings import BaseSettings
class AppEnvironment(str,enum.Enum):
DEVELOP = "development"
PRODUCTION = "production"
class Settings(BaseSettings):
ENVIRONMENT:AppEnvironment
API_VI_STR:str = "/api/v1"
PROJECT_NAME: str = "my-next-app13"
POSTGRES_SERVER:str
POSTGRES_USER: str
POSTGRES_PASSWORD: str
POSTGRES_DB: str
POSTGRES_PORT: str
SQLALCHEMY_DATABASE_URI: Optional[str] = None
@field_validator("SQLALCHEMY_DATABASE_URI",mode="after")
def assemble_db_Connection(cls,v:Optional[str],values:ValidationInfo)->Any:
if isinstance(v, str):
return v
return str(
PostgresDsn.build(
scheme="postgresql",
username=values.data.get("POSTGRES_USER"),
password=values.data.get("POSTGRES_PASSWORD"),
host=values.data.get("POSTGRES_SERVER"),
port=int(values.data.get("POSTGRES_PORT")),
path=f"{values.data.get('POSTGRES_DB') or ''}",
)
)
settings = Settings()
5-3..envファイルの作成
backendファイル直下に.envファイルを新規作成します。中身は下記のように書きます。
ENVIRONMENT='development'
POSTGRES_USER='ユーザー名'
POSTGRES_PASSWORD='パスワード'
POSTGRES_DB='データベース名'
POSTGRES_SERVER='localhost'
POSTGRES_PORT='5432'
6.データベースへ接続するための設定
SQLAlchemyを使ってデータベースへ接続します。前掲のappディレクトリ内にsession.pyという名前のファイルを新規作成しましょう。
session.pyの中身は、下記のように記載します。
from app.core.config import settings
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session,sessionmaker
if settings.SQLALCHEMY_DATABASE_URI:
engine = create_engine(
settings.SQLALCHEMY_DATABASE_URI,
pool_pre_ping=True,
)
SessionLocal = scoped_session(
sessionmaker(autocommit=False,autoflush=False,bind=engine)
)
if settings.ENVIRONMENT == "development":
db_info = f"Using database at (settings.SQLALCHEMY_DATABASE_URI)"
print(db_info)
else:
raise ValueError("SQLALCHEMY_DATABASE_URI is not set")
6-1.DB接続のテスト
接続はちゃんとできたかを確認するため、appフォルダの直下にtest_connection.pyを新規作成します。
from sqlalchemy import text
from app.core.session import engine
with engine.connect() as connection:
result = connection.execute(text("SELECT 'Hello, World!'"))
print(result.scalar())
7.マイグレーション設定
7-1.軽量マイグレーションツールAlembicをインストール
Alembicは、SQLAlchemyで使用するための軽量データベースマイグレーションツールです。Alembicを用いると、データベーススキーマの変更履歴を一元的に管理できます。
下記のコマンド使ってインストールします。
pipenv install alembic
7-2.Alembicの初期設定
Alembicをインストール完了後に、次のコマンドを使ってAlembicの初期設定を行います。
pipenv run alembic init migration
このコマンド実行後に、下記のようにalembic.iniファイルとmigrationディレクトリが生成されます。
7.3 alembic.iniとenv.pyの設定と紐づけ
alembic.iniファイルとmigration/env.pyファイルに、プロジェクトのデータベース設定を反映させるため下記の操作を行います。
7-3-1.alembic.iniを更新
sqlalchemy.urlの値を%(DB_URL)sに設定します。
sqlalchemy.url = %(DB_URL)s
7-3-2.env.pyの更新
migration/env.pyファイルを開き、以下の変更を加えましょう。
1.必要なモジュールをインポートし、configオブジェクトを取得する。
2.モデルのメタデータをインポートし、target_metadataに割り当てる。
3.config.set_section_optionでDB_URLを動的に設定する。
「👈」の箇所が、追加または修正の部分となります。
from logging.config import fileConfig
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from app.core.config import settings #👈追加
from app.db.base_class import Base #👈追加
from alembic import context
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config
# Interpret the config file for Python logging.
# This line sets up loggers basically.
if config.config_file_name is not None:
fileConfig(config.config_file_name)
# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
from app.models.user import User # noqa
target_metadata = Base.metadata # 👈修正
#target_metadata = None #コメントアウト
# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.
config.set_section_option("alembic", "DB_URL", settings.SQLALCHEMY_DATABASE_URI)#👈追加
def run_migrations_offline() -> None:
"""Run migrations in 'offline' mode.
This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.
Calls to context.execute() here emit the given string to the
script output.
"""
url = config.get_main_option("sqlalchemy.url")
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def run_migrations_online() -> None:
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
"""
connectable = engine_from_config(
config.get_section(config.config_ini_section, {}),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata
)
with context.begin_transaction():
context.run_migrations()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
8.マイグレーションファイル作成と実行
8-1.マイグレーションファイル作成
以下のコマンドを実行することで、マイグレーションファイルが自動生成されます。
pipenv run alembic revision --autogenerate -m "description_of_your_change"
8-2.マイグレーションの実行
マイグレーションを実行するには、以下のコマンドを使用します。
pipenv run alembic upgrade head
トラブルシューティング
(質問1)FastAPIで「pipenv run python -m app.test_connection」としたら下記のエラーが出た。
Loading .env environment variables...
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "C:\Users\xxx\Desktop\my-next-app13\backend\app\test_connection.py", line 1, in <module>
from sqlalchemy import text
ModuleNotFoundError: No module named 'sqlalchemy'
(回答)
ModuleNotFoundError: No module named 'sqlalchemy' は、実行されている仮想環境に SQLAlchemy がインストールされていないことが原因です。
以下のチェックポイントと解決方法を順番に試してください。
pipenv の仮想環境にSQLAlchemyが入っていないので、下記のコマンドを使ってインストールします。
pipenv install sqlalchemy
(質問2)ディレクトリを修正して「pipenv run python -m app.test_connection」としたら下記のエラーが出た。
Loading .env environment variables...
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "C:\Desktop\my-next-app13\backend\app\test_connection.py", line 2, in <module>
from app.core.session import engine
File "C:\Desktop\my-next-app13\backend\app\core\session.py", line 1, in <module>
from app.core.config import settings
File "C:\Desktop\my-next-app13\backend\app\core\config.py", line 4, in <module>
from pydantic import PostgresDsn,ValidationInfo,field_validator
ModuleNotFoundError: No module named 'pydantic'
ディレクトリ構造
----------------------------
backend/
app/
__init__.py
core/
__init__.py
session.py
test_connection.py
----------------------------
(回答)
ModuleNotFoundError: No module named 'pydantic' は、pipenv の仮想環境に Pydantic がインストールされていないのが原因です。
FastAPI + SQLAlchemy の構成ではPydanticは必須なので、単純にパッケージ追加すれば解決します。
✅ 解決方法:Pydantic をインストールする
FastAPI では Pydantic v2 系を推奨(今のFastAPIはv2を使う想定)
なのでpipenvで以下を実行してください:
pipenv install pydantic
pipenv install pydantic-settings
サイト
FastAPIとPostgreSQLの結合:モデル定義とマイグレーション入門
Full Stack TikTok Clone: NestJS, GraphQL, Prisma, Postgres, React, Apollo Client, Zustand & Tailwind


