🍣
# 6.4 ログイン API の実装
前回で accounts
アプリを作り、ユーザ・部署・ロールを管理できる環境が整った。
今回は Django REST Framework(DRF)を使って ログイン API を実装していく。
ここでは モデルと同じくファイルを分割する構成を採用する。
規模が大きくなっても見通しよく管理できるため、業務システムに向いている。
1. ディレクトリ構成
accounts/
models/
__init__.py
user.py
dept.py
role.py
user_dept.py
user_role.py
serializers/
__init__.py
auth.py
views/
__init__.py
auth.py
urls.py
admin.py
👉 モデルだけでなく、シリアライザ・ビューも機能単位で分割する。
2. DRF の設定
settings.py
に追加:
INSTALLED_APPS = [
...,
"rest_framework",
"corsheaders",
"accounts",
]
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
...
]
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.SessionAuthentication", # セッション認証
],
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAuthenticated",
],
}
👉 今回は セッション認証 を採用。
Vue からのリクエストで Cookie を使ってログイン状態を保持する。
3. シリアライザ
accounts/serializers/auth.py
from rest_framework import serializers
class LoginSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField()
👉 ユーザ名とパスワードを受け取るだけのシンプルなシリアライザ。
4. ビュー
accounts/views/auth.py
from django.contrib.auth import authenticate, login, logout
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from ..serializers.auth import LoginSerializer
from ..models import UserDept, UserRole
class LoginView(APIView):
permission_classes = [] # 未ログインでも使える
def post(self, request):
serializer = LoginSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = authenticate(
request,
username=serializer.validated_data["username"],
password=serializer.validated_data["password"],
)
if user is not None:
login(request, user)
return Response({"message": "ログイン成功"})
return Response({"error": "認証失敗"}, status=status.HTTP_401_UNAUTHORIZED)
class LogoutView(APIView):
def post(self, request):
logout(request)
return Response({"message": "ログアウトしました"})
class AuthStatusView(APIView):
def get(self, request):
if request.user.is_authenticated:
departments = [
{"code": ud.dept.code, "name": ud.dept.name}
for ud in UserDept.objects.filter(user=request.user)
]
roles = [ur.role.code for ur in UserRole.objects.filter(user=request.user)]
return Response({
"username": request.user.username,
"full_name": request.user.full_name,
"is_staff": request.user.is_staff,
"departments": departments,
"roles": roles,
})
return Response({"authenticated": False}, status=status.HTTP_401_UNAUTHORIZED)
👉
-
LoginView
… 認証成功ならセッションを開始 -
LogoutView
… セッションを破棄 -
AuthStatusView
… 現在ログインしているユーザの部署・ロールを返す
5. URL 設定
accounts/urls.py
from django.urls import path
from .views.auth import LoginView, LogoutView, AuthStatusView
urlpatterns = [
path("auth/login/", LoginView.as_view(), name="login"),
path("auth/logout/", LogoutView.as_view(), name="logout"),
path("auth/status/", AuthStatusView.as_view(), name="auth_status"),
]
project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("api/", include("accounts.urls")),
]
6. 動作確認
6.1 ログイン
curl -X POST -H "Content-Type: application/json" -d "{\"username\":\"t.yamada\",\"password\":\"pass123\"}" -c cookies.txt http://127.0.0.1:8000/api/auth/login/
6.2 認証確認
curl -X GET -b cookies.txt http://127.0.0.1:8000/api/auth/status/
レスポンス例:
{
"username": "taro",
"full_name": "山田 太郎",
"is_staff": true,
"departments": [
{"code": "A001", "name": "営業一課"}
],
"roles": ["order_approve"]
}
今回のゴール
- DRF で ログイン/ログアウト/認証確認 API を実装
- ディレクトリを分けて models / serializers / views を整理
- 認証済みユーザの部署・ロール情報を返せるようにした
- Vue 側からセッションを保持して API を叩ける準備が整った
次の展開
次は 6.5 Vue との接続編。
Vue 側に 共通 axios クライアント を用意し、今回のログイン API と認証状態を実際に呼び出してみる。
Discussion