ℹ️

Django Ninjaでアプリケーションを作成

2024/03/26に公開

アプリケーションの立ち上げ

今回は、プレスリリース用のシステムを作成します。

docker compose run backend python manage.py startapp press_sys

アプリケーションの登録

プロジェクトの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',
    'press_sys.apps.PressSysConfig', # add
]

モデルの設定

アプリケーションのmodels.pyのに必要なフィールドの設定をしていきます。

backend/press_sys/models.py
from accounts.models import CustomUser
from django.db import models

class Article(models.Model):
  author = models.ForeignKey(to = CustomUser, on_delete = models.CASCADE)
  title = models.CharField(max_length = 512)
  content = models.TextField(blank = True, null = True)
  release_date = models.DateField(blank = True, null = True)
  tel = models.CharField(max_length = 15, blank = True, null = True)
  created_at = models.DateTimeField(auto_now_add = True)
  
  def __str__(self):
    return f'{self.author.username}: {self.title}'
backend/press_sys/admin.py
from django.contrib import admin
from press_sys.models import Article

admin.site.register(Article)
docker compose run backend python manage.py makemigrations
docker compose run backend python manage.py migrate

それぞれを実行します。

Django Ninjaの設定

今回はDjango Ninjaを使用してAPIを開発していきます。
まずは初歩的な部分から設定していきます。

Djangoのモデルからスキーマを生成

Django NinjaはDjnagoで設定したモデルからAPI用のスキーマを生成することができます。
今回は、Djangoのモデルを作成したときのアプリケーションのディレクトリがそれぞれあるので、この中にschemaを定義するファイルを作成していきます。

accountsのschema

まずはForeignKeyにも設定しているaccountsディレクトリにschemas.pyを作成します。

backend/accounts/schemas.py
from .models import CustomUser
from ninja import ModelSchema

class CustomUserSchema(ModelSchema):
  class Config:
    model = CustomUser
    exclude = ['password', 'last_login', 'birth_date']

今回は、APIで情報を取得する時に含めたくないフィールドを指定しました。
excludeに配列でフィールド名を格納します。

Django Ninjaの公式ドキュメントはこちらです。
https://django-ninja.dev/guides/response/django-pydantic/

press_sysのschema

backend/press_sys/schemas.py
from datetime import datetime
from ninja import ModelSchema, Schema
from accounts.schemas import CustomUserSchema
from .models import Article

# Manual schema generation
class ArticleIn(Schema):
  author: str ## uuid
  title: str
  content: str

class ArticleOut(Schema):
  class Config:
    model = Article
    fields = '__all__'

Django Ninjaの公式ドキュメントで言及している記事はこちら
https://django-ninja.dev/guides/response/django-pydantic/

APIのコア部分を作る

それではDjango Ninjaを使用して実際にAPIを作成していきます。

routerの設定

Django NinjaでもFastAPIと同様にrouterの概念があり、複数のモジュールでAPIを持つことができるようになっています。
それでは実際にAPIを作成していきます。

backend/press_sys/api.py
from typing import List

from accounts.models import CustomUser
from django.shortcuts import get_object_or_404

from ninja import Router

from .models import Article
from .schemas import ArticleIn, ArticleOut

router = Router()

@router.get('/article/{id}', response = ArticleOut)
def get_article(request, id: int):
  article = get_object_or_404(Article, id = id)
  return article

@router.get('/articles', response = List[ArticleOut])
def get_articles(request):
  articles = Article.objects.all()
  return articles

@router.post('/article/create')
def create_article(request, payload: ArticleIn):
  data = payload.dict()
  try:
    author = CustomUser.objects.get(uuid = data['author'])
    del data['author'] # dataからauthor情報を除外し、article情報のみを含むように変換
    article = Article.objects.create(author = author, **data)
    return {
      'detail': 'Article has been successfully created.',
      'article': article.id
    }
  except CustomUser.DoesNotExist:
    return {
      'detail': 'The specific user cannot be found.'
    }

routerに関するドキュメントはこちらです。
https://django-ninja.dev/guides/routers/

APIエンドポイントの作成

Django Ninjaの場合、apiのエンドポイントは単一のエンドポイントとなります。
NinjaAPIのインスタンスを作成し、この後設定する各API routerを読み込みます。

backend/project/urls.py
from django.contrib import admin
from django.urls import path
from ninja import NinjaAPI

from press_sys.api import router as article_router

api = NinjaAPI()
api.add_router('/press/', article_router, tags = ["Article"])

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', api.urls)
]

urls.pyでArticleに関するrouterを読み込み、アクセスできるようにしています。
Django NinjaではOpenAPIの使用しているため、単一のエンドポイントから複数のエンドポイントにアクセス、実行できます。

APIの確認

docker compose up

サーバーを立ち上げて、http://0.0.0.0:8000/api/docs/にアクセスし、最終的にこのような画面が表示されれば完成です。
最終的なAPIの画面

今回のAPI作成はこちらの記事を参考にしています。
https://testdriven.io/blog/django-and-pydantic/#django-ninja

Discussion