## 経緯 ミニマムプロジェクトで動作確認したいときに毎回つくるのは心理的ハードルが高いので、[[🦉Toki]]でサクっと作れるようにしたい。 以下のような手順を想定。 <div class="link-card-v2"> <div class="link-card-v2-site"> <img class="link-card-v2-site-icon" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" /> <span class="link-card-v2-site-name">Minerva</span> </div> <div class="link-card-v2-title"> 📜2025-09-24 Django REST frameworkを学習してみる </div> <div class="link-card-v2-content">仕事でDjango REST frameworkを使う必要が生じ、機能が多く把握しきれなかったため、Django 4.2とDRF 3.16.1を用いて体系的な学習を開始した。環境構築では依存関係やバージョン選定、PostgreSQL導入、psycopg3の利用などに取り組み、SerializerやModelSerializerの実装、APIエンドポイント作成、Brunoによる動作確認までを段階的に実施した。</div> <img class="link-card-v2-image" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/activity.webp" /> <a data-href="📜2025-09-24 Django REST frameworkを学習してみる" class="internal-link"></a> </div> %%[[📜2025-09-24 Django REST frameworkを学習してみる]]%% ## 手順をスクリプト化 ```console mkdir drf-sandbox cd drf-sandbox uv init uv add django==4.2 djangorestframework django-stubs django-types ``` ## テンプレ 以下のコマンドで生成されるものはテンプレにしておきたい ```console uv run django-admin startproject project . cd project uv run django-admin startapp app rm main.py ``` ```console cd .. uv run python manage.py makemigrations \ && uv run python manage.py migrate ``` ## ベースファイル `settings.py` はこちらで作成したほうがいい。`rest_framework` を入れないといけないので。 `project/app/apps.py` ```python from django.apps import AppConfig class AppConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" name = "project.app" ``` `project/app/models.py` ```python from django.contrib.auth.models import User from django.db import models from rest_framework.fields import uuid ANIMAL_KIND = ( ("dog", "犬"), ("cat", "猫"), ("owl", "フクロウ"), ("gorilla", "ゴリラ"), ) class Animal(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField(max_length=100, blank=True, default="") description = models.TextField() proper = models.BooleanField(default=False) kind = models.CharField(choices=ANIMAL_KIND, default="owl", max_length=32) owner = models.ForeignKey(User, related_name="animals", on_delete=models.CASCADE) created = models.DateTimeField(auto_now_add=True) class Meta: ordering = ["created"] ``` `project/app/serializers.py` ```python from django.contrib.auth.models import User from rest_framework import serializers from project.app.models import Animal class AnimalSerializer(serializers.ModelSerializer): class Meta: model = Animal fields = "__all__" class UserSerializer(serializers.ModelSerializer): animals = AnimalSerializer(many=True) class Meta: model = User fields = ["id", "username", "animals"] ``` ## データ初期化ファイル ```console uv run python manage.py shell < init.py ``` `init.py` ```python from django.contrib.auth.models import User from django.db import transaction from project.app.models import Animal with transaction.atomic(): User.objects.all().delete() User.objects.create_superuser(id=1, username="admin", password="password") User.objects.bulk_create( [ User(id=2, username="ミネルヴァ"), User(id=3, username="オブシディア"), User(id=4, username="ネオちゃん"), ] ) with transaction.atomic(): Animal.objects.all().delete() Animal.objects.bulk_create( [ Animal( name="みみぞう", description="ピーッ!", proper=True, kind="owl", owner_id=2, # ミネルヴァ ), Animal( name="タツヲ", description="ウホ♡", proper=True, kind="gorilla", ), Animal( name="ポチ", description="ワンワン!", proper=False, kind="dog", owner_id=4, # ネオちゃん ), ] ) ``` ## 動作確認コマンド ```console curl -s "localhost:8000/users/" | jq curl -s "localhost:8000/animals/" | jq ```