ℹ️
Django Ninjaでアプリケーションを作成
アプリケーションの立ち上げ
今回は、CustomUserをもとにしたユーザー管理用のシステムを作成します。
poetry run python manage.py startapp accounts
アプリケーションの登録
プロジェクトのsettings.pyにアプリケーションを登録します。
backend/project/settings.py
INSTALLED_APPS = [
'accounts.apps.AccountsConfig', # add
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
モデルの設定
accountsのmodels.pyとadmin.pyはすでに作成していますので、こちらの記事を参考にしてください。
マイグレーションを実行していない場合は、下記により実行してください。
poetry run python manage.py makemigrations
poetry run python manage.py migrate
Django Ninjaの設定
今回はDjango Ninjaを使用してAPIを開発していきます。
Djangoのモデルからスキーマを生成
Django NinjaはDjnagoで設定したモデルからAPI用のschemaを生成することができます。
Django Ninjaの公式ドキュメントはこちらです。
APIのコア部分を作る
それではDjango Ninjaを使用して実際にAPIを作成していきます。
routerの設定
Django NinjaでもFastAPIと同様にrouterの概念があり、複数のモジュールでAPIを持つことができるようになっています。
それでは実際にAPIを作成していきます。
backend/accounts/api.py
from ninja import Router
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import get_object_or_404
from django.utils.translation import gettext_lazy as _
from accounts.models import CustomUser
from accounts.schemas import UserOut, UserCreate, TokenSchema
from django.contrib.auth.hashers import make_password # パスワードハッシュ化のため
from typing import List, Optional
from .utils import create_jwt_token
from .auth import JWTAuth
router = Router(tags="Auth API")
@router.post("/register/", response=UserOut, summary="ユーザー登録")
def register_user(request, user_data: UserCreate):
"""
ユーザー登録を行うAPIエンドポイント。
"""
# パスワードをハッシュ化
hashed_password = make_password(user_data.password)
# usernameが既に存在するか確認
if CustomUser.objects.filter(username=user_data.username).exists():
raise Exception("Username already exists") # エラーメッセージを返す
# emailが既に存在するか確認
if CustomUser.objects.filter(email=user_data.email).exists():
raise Exception("Email already exists") # エラーメッセージを返す
user = CustomUser.objects.create(
username=user_data.username,
email=user_data.email,
password=hashed_password, # ハッシュ化されたパスワードを保存
is_staff=user_data.is_staff,
is_superuser=user_data.is_superuser,
)
return UserOut.from_orm(user)
@router.post("/login/", response=TokenSchema, summary="ログイン")
def user_login(request, email: str, password: str):
"""
ログインAPIエンドポイント。
"""
user = authenticate(request, email=email, password=password)
if user:
login(request, user)
token = create_jwt_token(user)
return {"access_token": token}
else:
raise Exception("Invalid credentials") # エラーメッセージを返す
@router.post("/logout/", summary="ログアウト")
def user_logout(request):
"""
ログアウトAPIエンドポイント。
"""
logout(request)
return {"message": "Logged out"}
@router.get(
"/users/me/", response=UserOut, auth=JWTAuth(), summary="ログインユーザー情報"
)
def get_me(request):
"""
ログインしているユーザーの情報を返すAPIエンドポイント。
"""
user = request.auth
return UserOut.model_validate(user)
@router.get(
"/users/{user_uuid}",
response=UserOut,
auth=JWTAuth(),
summary="ユーザーIDでユーザー取得",
)
def get_user(request, user_uuid: str):
"""
指定されたユーザーIDのユーザー情報を返すAPIエンドポイント。
"""
user = get_object_or_404(CustomUser, uuid=user_uuid) # uuidでユーザーを取得
return UserOut.model_validate(user)
@router.get(
"/users/", response=List[UserOut], auth=JWTAuth(), summary="ユーザー一覧取得"
)
def get_users(request, is_staff: Optional[bool] = None):
"""
ユーザー一覧を取得するAPIエンドポイント。
is_staffでフィルタリングも可能。
"""
users = CustomUser.objects.all()
if is_staff is not None:
users = users.filter(is_staff=is_staff)
user_list = [] # UserOutのリストを格納する
for user in users:
user_info = UserOut(
uuid=user.uuid,
username=user.username,
email=user.email,
is_active=user.is_active,
is_staff=user.is_staff,
date_joined=user.date_joined,
)
user_list.append(user_info)
return user_list
routerに関するドキュメントはこちらです。
APIエンドポイントの作成
Django Ninjaの場合、apiのエンドポイントは単一のエンドポイントとなります。
NinjaAPIのインスタンスを作成し、この後設定する各API routerを読み込みます。
backend/backend/urls.py
from django.contrib import admin
from django.urls import path
from ninja import NinjaAPI
from accounts.api import router as accounts_router
api = NinjaAPI(
description="Admin page: [Admin](http://127.0.0.1:8000/admin)",
)
api.add_router("/accounts/", accounts_router, tags=["Accounts"])
urlpatterns = [path("admin/", admin.site.urls), path("api/", api.urls)]
urls.pyでaccountsに関するrouterを読み込み、アクセスできるようにしています。
Django NinjaではOpenAPIの使用しているため、単一のエンドポイントから複数のエンドポイントにアクセス、実行できます。
APIの確認
poetry run python manage.py runserver
サーバーを立ち上げて、http://0.0.0.0:8000/api/docs/にアクセスし、最終的にこのような画面が表示されれば完成です。

今回のAPI作成はこちらの記事も参考にしています。
Discussion