プログラミングを頑張る土木系専攻大学院生のブログ

主にプログラミングについて開発備忘録的な形で投稿しています。

views.pyの記述を楽に!シリアライザをつかってみる レシピ提案アプリ開発②

 

こんにちは!前回の記事では、主にアプリの要件定義を書いてみました。

 

siip.hateblo.jp

 

これまでは Django 本体のみで開発しており、Django関連のライブラリは使ったことがありませんでした。

より効率的な開発を目指して
Django REST Framework (DRF) を導入し、まずはリアライザーから使ってみることにしました!

views.pyの記述をだいぶ簡潔にすることができます。

バリデーション処理やデータ変換処理を簡潔に行えるので参考になれば幸いです。

 


🔍 調べたこと

参考にさせていただいた記事はこちらです👇


リアライザーを使う目的とは?

リアライザーは Django REST Framework の中核機能で、主に次の2つの役割を担っています👇


データの変換

データベースのモデルオブジェクトをJSON形式に変換し、APIレスポンスとして返す

クライアントから送信されたJSONデータをモデルオブジェクトに変換し、データベースに保存する


データのバリデーション

  • 入力されたデータの形式や必須項目のチェックを自動で行ってくれる

  • 例えば文字数や空欄チェック、ユニーク制約などもここで確認できます!


📝 まとめると →
views.py内で手書きしていたバリデーション処理やデータ変換処理を、シリアライザに任せられるので、
コードがスッキリしてメンテナンスしやすくなります!


🧰 ライブラリ準備

まず、django-extensionsをインストールして、settings.py に追加しました。

INSTALLED_APPS = [
    ...
    'django_extensions',  # Django Extensions を追加
    'ingredients',        # 食材アプリ
    'recipes',            # レシピアプリ
]

🏗 実際のモデル(models.py)

📁 recipes/models.py(レシピ提案アプリ)

from django.db import models
from ingredients.models import Ingredient

class Category(models.Model):
    name = models.CharField(max_length=50)  # カテゴリ名

    def __str__(self):
        return self.name

class Recipe(models.Model):
    name = models.CharField(max_length=100, unique=True, help_text="レシピ名を入力してください") 
    url = models.URLField(unique=True, help_text="YouTubeのURLを入力してください")  
    thumbnail = models.URLField(help_text="サムネイル画像のURLを入力してください")  
    notes = models.TextField(blank=True, null=True, help_text="備考を入力してください") 
    ingredients = models.ManyToManyField(Ingredient, related_name='recipes', help_text="使用する食材を選択してください")  
    categories = models.ManyToManyField(Category, related_name='recipes', help_text="カテゴリを選択してください") 
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

📁 ingredients/models.py(食材登録アプリ)

from django.db import models

class Ingredient(models.Model):
    TYPE_CHOICES = [
        ('肉・魚・大豆・卵', '肉・魚・大豆・卵'),
        ('野菜', '野菜'),
        ('米・麺・パスタ', '米・麺・パスタ'),
        ('その他', 'その他'),
    ]
    name = models.CharField(max_length=100, unique=True, help_text="食材名を入力してください")  # 食材名
    reading = models.CharField(max_length=100, help_text="食材の読み方を入力してください")  # 読み方
    type = models.CharField(max_length=50, choices=TYPE_CHOICES, help_text="食材の種類を選択してください")  # 種類

    def __str__(self):
        return self.name

🗂 E-R図(モデルの関係)

以下ではモデルを扱うので↓の図を参考に!

E-R図

 


🧩 serializers.py の記述

レシピやカテゴリ、食材のモデルをJSONに変換するために、以下のように serializers.py を記述しました👇

from rest_framework import serializers
from .models import Recipe, Category
from ingredients.models import Ingredient
from ingredients.serializers import IngredientSerializer

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = '__all__'

class RecipeSerializer(serializers.ModelSerializer):
    ingredients = serializers.PrimaryKeyRelatedField(many=True, queryset=Ingredient.objects.all())
    categories = serializers.PrimaryKeyRelatedField(many=True, queryset=Category.objects.all())

    class Meta:
        model = Recipe
        fields = '__all__'

🔍 解説:RecipeSerializer のポイント

  • ingredientscategories はどちらも ManyToManyField なので、PrimaryKeyRelatedField を使用し、ネストして使用しています

  • many=True を付けることで、複数のデータ(リスト形式)として扱うように指定

  • queryset=Model.objects.all() で、関連モデルを正しく取得できるようにしています


ネストって?

  • 例えば、Ingredient や Category の詳細情報も含めて返したいときは、
    ネスト(入れ子)されたシリアライザーを使います👇

class RecipeSerializer(serializers.ModelSerializer):
    ingredients = IngredientSerializer(many=True, read_only=True)
    categories = CategorySerializer(many=True, read_only=True)

    class Meta:
        model = Recipe
        fields = '__all__'

🔧 一部のフィールドだけ指定する例

開発中などで表示項目を絞りたい場合は、次のように fields にリストで明示的に書くことも可能です👇

class RecipeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Recipe
        fields = ['id', 'name', 'url', 'ingredients', 'categories']

🧐 なぜ一部フィールドにするのか?

  1. 不要なデータを省ける
     → 通信効率の向上、見やすさUP

  2. セキュリティのため
     → ユーザー情報など、外に出したくない情報は除外

  3. データの簡潔化
     → クライアント側での処理が楽になる!


📦 例:フィールドを絞ったレスポンス

{
  "id": 1,
  "name": "鶏むね肉の照り焼き",
  "url": "https://youtube.com/example",
  "ingredients": [
    { "id": 1, "name": "鶏むね肉", "reading": "とりむねにく", "type": "肉" },
    { "id": 2, "name": "醤油", "reading": "しょうゆ", "type": "調味料" }
  ],
  "categories": [
    { "id": 1, "name": "主菜" }
  ]
}

➡️ すっきりして見やすい!
ただし、thumbnail などが含まれないため、必要に応じてフィールドを調整しましょう。


 

💬 まとめと感想

初めてDRFのシリアライザーを触ってみましたが、
正直、**「もっと早く知っておけばよかった…」**というレベルの便利さでした。

レシピ提案アプリ開発記事一覧はこちらから ↓

siip.hateblo.jp