見出し画像

Django REST API 開発の詳細な手順


1.Djangoの基礎知識を学ぶ:

  • Pythonプログラミング言語に慣れる。

例えば下記の内容を確認してください。

①Pythonでのコメントの書き方は?
--回答: コメントは「#」を使用して行単位で記述します。

②Pythonでの変数の宣言方法は?
--回答: 変数は代入演算子「=」を使用して宣言します。

③Pythonでのリストとタプルの違いは?
--回答: リストは変更可能な要素の集合であり、タプルは変更できない要素の集合です。

④Pythonのif文の書式は?
--回答:

if 条件:
条件がTrueの場合に実行するコード

⑤Pythonでのforループとwhileループの違いは?
--回答: forループは繰り返し回数が決まっている場合に使用し、whileループは条件がTrueの間繰り返す場合に使用します。

  • モデル(Models)、ビュー(Views)、URL設定(URL Configuration)、テンプレート(Templates)など、Djangoフレームワークの基本的な概念を学ぶ。

例えば下記の内容を確認してください。

①Djangoでのモデルとは何ですか?
--回答: Djangoでのモデルはデータベースのテーブルと対応するクラスであり、データの定義や操作を行います。

②Djangoでモデルを定義するためのクラスはどのように作成しますか?
--回答: models.pyファイル内に、django.db.models.Modelクラスを継承したクラスを作成します。

③Djangoでのビューとは何ですか?
--回答: Djangoでのビューはユーザーからのリクエストを受け取り、適切な処理を行いレスポンスを返す関数またはクラスです。

④Djangoでビューを作成するためのクラスはどのように作成しますか?
--回答: views.pyファイル内に、django.views.Viewクラスを継承したクラスを作成します。

⑤DjangoのURL設定(URL Configuration)とは何ですか?
--回答: DjangoのURL設定は、URLとビューのマッピングを定義するためのルーティングの設定です。

⑥DjangoでURL設定を行うためのファイルはどれですか?
--回答: urls.pyファイルです。

⑦Djangoのマイグレーションとは何ですか?
--回答: Djangoのマイグレーションは、データベースのスキーマの変更や更新を管理する仕組みです。

⑧Djangoでマイグレーションを実行するコマンドは何ですか?
--回答: python manage.py migrateコマンドです。

⑨Djangoでのスーパーユーザーの作成方法は?
--回答: python manage.py createsuperuserコマンドを使用します。

⑩Djangoのコマンドラインシェルにアクセスするコマンドは何ですか?
--回答: python manage.py shellコマンドです。

⑪Djangoの開発サーバーを起動するコマンドは何ですか?
--回答: python manage.py runserverコマンドです。

2.Djangoのインストールと設定:


pipを使用してDjangoフレームワークをインストールする。
新しいDjangoプロジェクトを作成する。
データベースやその他の必要な設定を行う。

2.1-Djangoのインストール:
Djangoをインストールするには、pipを使用します。
pipはPythonパッケージを管理するためのツールです。
以下のコマンドを実行してDjangoをインストールします。

pip install django

2.2-新しいDjangoプロジェクトの作成:
Djangoプロジェクトを作成するには、以下のコマンドを実行します。

django-admin startproject project_name
#上記のproject_nameは、作成するプロジェクトの名前です。
#このコマンドを実行すると、プロジェクト用のディレクトリが作成され、
#必要なファイルとディレクトリが生成されます。

2.3-データベースやその他の設定:
Djangoプロジェクトでは、データベースやその他の必要な設定を行う必要があります。

  • データベース設定: データベースを使用する場合、DjangoではデフォルトでSQLiteが設定されています。

  • もし他のデータベースを使用する場合は、settings.pyファイル内のDATABASESセクションを編集してデータベースの設定を変更します。

  • その他の設定: Djangoプロジェクトでは、静的ファイルの配置場所、メディアファイルの設定、言語やタイムゾーンの設定など、さまざまな設定が可能です。これらの設定はsettings.pyファイル内で行います。

上記の設定を行うことで、Djangoプロジェクトの基本的な設定が完了します。

3.データモデルの設計・定義:


データベース内のテーブルやデータ構造を表現するために、アプリケーションの要件に基づいてデータモデルを設計・定義します。
データモデルは、アプリケーションが扱うデータの属性や関係を定義するものであり、データの保存、取得、更新、削除などの操作を可能にします。

3.1--Djangoのモデルクラス:
Djangoでは、データモデルを定義するためにモデルクラスを使用します。
モデルクラスはDjangoのdjango.db.models.Modelクラスを継承して作成され、データベース内のテーブルとの対応関係を持ちます。

3.2--モデルのフィールド:
モデルクラス内でフィールドを定義することで、データベースのテーブル内のカラムと対応付けられます。
フィールドはデータの種類を表し、例えばテキスト、数値、日付などのデータ型を持ちます。
Djangoでは、様々なフィールドタイプ(例:CharField、IntegerField、DateFieldなど)が提供されており、それぞれのフィールドには異なるオプション(例:最大長さ、デフォルト値など)が設定可能です。

例えば、以下のようなモデルクラスがあるとします。

from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    created_at = models.DateTimeField(auto_now_add=True)

上記の例では、Productというモデルが定義されています。
モデル内で定義されている各フィールドの詳細を見てみましょう。

  1. nameフィールド: テキストデータを格納するためのフィールドです。CharFieldを使用して定義されており、max_lengthオプションで最大文字数を指定することができます。

  2. priceフィールド: 金額データを格納するためのフィールドです。DecimalFieldを使用して定義されており、max_digitsオプションで整数部分と小数部分の桁数の合計を指定し、decimal_placesオプションで小数部分の桁数を指定します。

  3. created_atフィールド: 日付と時刻を格納するためのフィールドです。DateTimeFieldを使用して定義されており、auto_now_add=Trueオプションを指定することで、オブジェクトが作成された時刻が自動的に設定されます。

これらのフィールド定義により、Productモデルの各インスタンスは、名前、価格、作成日時の情報を持つことができます。このモデルを使用して、データベースのテーブルとしての構造を定義し、データの保存や取得などの操作を行うことができます。

3.3--関連の定義:
データモデルが複数のテーブル間で関連を持つ場合、Djangoでは関連フィールドを使用して関連を定義します。
例えば、外部キー(ForeignKey)を使用して他のテーブルとの一対多の関係を定義することができます。
関連フィールドを使用することで、データベースのテーブル間での参照や結合が容易になります。

例えば、外部キー(ForeignKey)を使用して他のテーブルとの一対多の関係を定義することができます。

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    # 他のフィールド...

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    # 他のフィールド...

上記の例では、AuthorBookという2つのモデルが定義されています。Bookモデルにはauthorという外部キーフィールドがあり、Authorモデルとの関連を表しています。

この関連フィールドの定義により、Bookモデルの各インスタンスは、特定のAuthorモデルと関連付けられます。on_delete=models.CASCADEの指定により、関連するAuthorが削除された場合には、関連するBookも一緒に削除される設定になります。

このように関連フィールドを使用することで、データベースのテーブル間での参照や結合が容易になります。例えば、Bookモデルのインスタンスから関連するAuthorモデルの情報にアクセスすることができます。

なお、上記の例では一対多の関係を示していますが、Djangoでは他にも多対多の関係や一対一の関係を表現するための関連フィールドが提供されています。

【多対多の関係】
多対多の関係では、一つのモデルが複数の他のモデルと関連付けられます。Djangoでは、ManyToManyFieldを使用して多対多の関係を定義します。

from django.db import models

class Student(models.Model):
    name = models.CharField(max_length=100)
    # 他のフィールド...

class Course(models.Model):
    name = models.CharField(max_length=100)
    students = models.ManyToManyField(Student)
    # 他のフィールド...

上記の例では、StudentCourseという2つのモデルが定義されています。CourseモデルにはstudentsというManyToManyFieldがあり、複数のStudentモデルとの多対多の関係を表現しています。この関連フィールドを使用することで、あるCourseに複数のStudentを関連付けることができます。

【一対一の関係】
一対一の関係では、一つのモデルが他のモデルと一対一の関係を持ちます。Djangoでは、OneToOneFieldを使用して一対一の関係を定義します。

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=100)
    # 他のフィールド...

class Profile(models.Model):
    person = models.OneToOneField(Person, on_delete=models.CASCADE)
    # 他のフィールド...

上記の例では、PersonProfileという2つのモデルが定義されています。ProfileモデルにはpersonというOneToOneFieldがあり、Personモデルとの一対一の関係を表現しています。この関連フィールドを使用することで、一つのPersonモデルと一つのProfileモデルを関連付けることができます。

関連フィールドを使用することで、多対多の関係や一対一の関係を簡潔に定義することができます。

4.メソッドの定義:


モデルクラス内にメソッドを定義することで、モデルに関連するさまざまな操作や振る舞いを実装することができます。
例えば、データのバリデーションや加工、特定の操作を行うためのメソッドを定義することができます。

from django.db import models
import datetime

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=100)
    publication_year = models.IntegerField()

    def is_published_this_year(self):
        """
        本が今年発行されたかどうかを判定します。
        """
        current_year = datetime.date.today().year
        return self.publication_year == current_year

    def get_author_full_name(self):
        """
        著者のフルネームを取得します。
        """
        return f"{self.author}さん"

    def get_book_details(self):
        """
        本の詳細情報を取得します。
        """
        return f"{self.title} ({self.author}), {self.publication_year}"

上記の例では、Bookというモデルが定義されています。Bookモデルにはtitleauthorpublication_yearというフィールドがあります。また、モデルクラス内に3つのメソッドが定義されています。

  1. is_published_this_year(self)メソッドは、本の発行年が現在の年と一致するかどうかを判定します。publication_yearと現在の年を比較し、結果を返します。

  2. get_author_full_name(self)メソッドは、著者のフルネームを返します。authorフィールドに格納されている著者名に「さん」を付け加えた文字列を返します。

  3. get_book_details(self)メソッドは、本の詳細情報を返します。titleauthorpublication_yearを組み合わせた文字列を返します。

モデルの定義は、Djangoの重要な機能の一つであり、アプリケーションのデータ構造を柔軟に設計・管理することができます。データモデルの設計はアプリケーションの要件に合わせて行う必要があり、正確な定義が重要です。

5.シリアライザ(Serializers)の作成:

  • Djangoのシリアライザを使用してモデルのシリアライズおよび逆シリアライズのルールを定義する。

  • シリアライザはモデルインスタンスをJSONなどの形式に変換し、リクエストデータのバリデーションと逆シリアライズを処理する役割を担う。

シリアライザ(Serializers)は、Djangoの機能の一部であり、モデルのシリアライズ(変換)および逆シリアライズ(逆変換)のルールを定義するために使用されます。
シリアライザは、モデルインスタンスをJSONやXMLなどの形式に変換し、クライアントからのリクエストデータをバリデーションして処理する役割を担います。

5.1--シリアライザクラスを定義する:
シリアライザは、serializersモジュールから継承されるPythonクラスです。シリアライザクラス内では、モデルのフィールドと対応するシリアライザフィールドを定義します。

例えばPersonモデルをシリアライズするためのシリアライザクラスを作成しています。

from rest_framework import serializers
from .models import Person

class PersonSerializer(serializers.ModelSerializer):
    # モデルとの関連付け
    class Meta:
        model = Person# Personモデルと関連付ける
        fields = ['id', 'name', 'age'] # シリアライズするフィールド

    # フィールドの定義
    id = serializers.IntegerField(read_only=True) # IDフィールド(読み取り専用)
    name = serializers.CharField(max_length=100)# 名前フィールド
    age = serializers.IntegerField()# 年齢フィールド

    # バリデーションや振る舞いを定義するメソッド
    def validate_age(self, value):
        if value < 0:
            raise serializers.ValidationError("年齢は0以上である必要があります。")
        return value

このコードでは、serializers.ModelSerializerを継承したPersonSerializerクラスを定義しています。Metaクラス内で、シリアライズする対象のモデルであるPersonモデルとシリアライズするフィールドを指定しています。

フィールドの定義では、各モデルフィールドに対応するシリアライザフィールドを定義しています。例えば、nameフィールドにはserializers.CharFieldを使用し、ageフィールドにはserializers.IntegerFieldを使用しています。

また、validate_ageメソッドでは、ageフィールドのバリデーションをカスタマイズしています。ここでは、年齢が0未満の場合にはバリデーションエラーを発生させるようにしています。

5.2--逆シリアライズの定義:
シリアライザクラス内で、create()やupdate()などのメソッドをオーバーライドすることで、逆シリアライズの処理を定義します。これにより、リクエストデータをもとに新しいモデルインスタンスを作成したり、既存のモデルインスタンスを更新したりすることができます。

例えばシリアライザクラス内でcreate()update()メソッドをオーバーライドしています。

from rest_framework import serializers
from .models import Person

class PersonSerializer(serializers.ModelSerializer):
    name = serializers.CharField(max_length=100)
    age = serializers.IntegerField()

    class Meta:
        model = Person
        fields = ['id', 'name', 'age']

    def create(self, validated_data):
        # リクエストデータから新しいPersonインスタンスを作成
        return Person.objects.create(**validated_data)

    def update(self, instance, validated_data):
        # リクエストデータを使用して既存のPersonインスタンスを更新
        instance.name = validated_data.get('name', instance.name)
        instance.age = validated_data.get('age', instance.age)
        instance.save()
        return instance

create()メソッドは、リクエストデータを受け取り、そのデータを使用して新しいPersonインスタンスを作成しています。validated_dataはバリデーションが行われたデータです。このメソッドでは、Person.objects.create()を使用して新しいインスタンスを作成しています。

update()メソッドは、既存のPersonインスタンスとリクエストデータを受け取り、インスタンスを更新しています。validated_dataから更新するフィールドの値を取得し、既存のインスタンスを保存しています。

create()メソッド:
create()メソッドは、新しいオブジェクトを作成するために使用されます。
一般的に、POSTリクエストなどで新しいデータを作成する際に呼び出されます。
create()メソッドは、バリデーションが完了したデータを受け取り、それを使用して新しいインスタンスを作成します。
作成されたインスタンスはデータベースに保存されます。
create()メソッドは、シリアライザのsave()メソッド内部で呼び出されることがあります。

update()メソッド:
update()メソッドは、既存のオブジェクトを更新するために使用されます。
一般的に、PUTやPATCHなどのリクエストで既存のデータを更新する際に呼び出されます。
update()メソッドは、バリデーションが完了したデータと既存のインスタンスを受け取ります。
update()メソッド内で、受け取ったデータを使用して既存のインスタンスを更新します。
更新されたインスタンスはデータベースに保存されます。
update()メソッドは、シリアライザのsave()メソッド内部で呼び出されることがあります。

6.ビュー(Views)の作成:

  • クラスベースまたは関数ベースのビューを作成し、APIのリクエストとレスポンスを処理する。

  • GET、POST、PUT、DELETEなどの異なるHTTPメソッドの処理ロジックを定義する。

  • シリアライザを使用してデータをシリアライズおよび逆シリアライズする。

from rest_framework import generics
from .models import MyModel
from .serializers import MySerializer

class MyView(generics.ListCreateAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer

上記のコードでは、MyViewというクラスベースビューを定義しています。ListCreateAPIViewを継承しています。

queryset変数には、ビューが操作するモデルのデータベースクエリセットを指定します。上記の例では、MyModelモデルの全てのオブジェクトを取得しています。

serializer_class変数には、ビューで使用するシリアライザクラスを指定します。上記の例では、MySerializerを使用しています。

クラスベースビューでは、異なるHTTPメソッド(GET、POST、PUT、DELETEなど)に対して、異なるアクション(リスト表示、作成、更新、削除など)を定義することができます。

上記の例では、ListCreateAPIViewを継承しているため、GETメソッドに対してはリスト表示のロジックが、POSTメソッドに対しては作成のロジックが自動的に提供されます。これにより、ビューがリクエストを受け取り、モデルのデータをシリアライズしてレスポンスとして返す処理が行われます。

Django REST Frameworkで提供される基本的なビュークラスには、以下のような種類があります。

  1. APIView: 基本的なAPIビューを提供するクラス。HTTPメソッドごとの処理を自分で実装する必要があります。

  2. GenericAPIView: データベースモデルやクエリセットと連携するための機能を提供するクラス。APIViewを拡張し、一般的なデータ操作に関連した便利な機能を提供します。

  3. ListAPIView: リスト表示を行うためのクラス。データベースモデルやクエリセットからデータを取得してリストとして返します。

  4. RetrieveAPIView: 単一のデータを取得するためのクラス。データベースモデルやクエリセットから指定された条件に一致するデータを取得して返します。

  5. CreateAPIView: データ作成を行うためのクラス。新しいデータをデータベースに保存します。

  6. UpdateAPIView: データの更新を行うためのクラス。指定されたデータを更新します。

  7. DestroyAPIView: データの削除を行うためのクラス。指定されたデータを削除します。

これらのクラスは、Django REST Frameworkのビューの基礎を提供し、異なるデータ操作に対応しています。開発者はこれらのクラスを継承し、必要な処理を実装することで、APIの振る舞いをカスタマイズすることができます。

まず、APIViewはDjango REST Frameworkで提供される基本的なビュークラスです。APIViewを継承することで、HTTPメソッドごとの処理を自分で実装することができます。以下に例を示します。

from rest_framework.views import APIView
from rest_framework.response import Response

class MyView(APIView):
    def get(self, request):
        # GETメソッドの処理を実装する
        # モデルのデータを取得し、シリアライズしてレスポンスとして返す

    def post(self, request):
        # POSTメソッドの処理を実装する
        # リクエストデータを逆シリアライズし、新しいモデルインスタンスを作成し保存する

上記の例では、MyViewクラスがAPIViewを継承しており、get()メソッドとpost()メソッドを実装しています。それぞれGETメソッドとPOSTメソッドの処理を記述します。

一方、ListCreateAPIViewAPIViewをベースにした便利なビュークラスです。ListCreateAPIViewを継承することで、リスト表示と作成の処理を自動的に提供します。以下に例を示します。

from rest_framework import generics
from .models import MyModel
from .serializers import MySerializer

class MyView(generics.ListCreateAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer

上記の例では、MyViewクラスがListCreateAPIViewを継承しています。ListCreateAPIViewはリスト表示と作成の処理を提供するため、querysetserializer_classの設定だけで十分です。GETメソッドでのリスト表示とPOSTメソッドでの作成処理が自動的に処理されます。

ListCreateAPIViewAPIViewの機能を組み合わせているため、より簡潔で効率的なコードを書くことができます。また、より一般的なCRUD(Create, Retrieve, Update, Delete)操作に対応しています。

したがって、APIViewを使用する場合は、すべてのHTTPメソッドの処理を個別に実装する必要があります。一方、ListCreateAPIViewを使用すると、リスト表示と作成の処理を自動的に提供することができます。適切なクラスを選択することで、コードの可読性と保守性を向上させることができます。

以下のソースコードは、Django REST FrameworkのRetrieveAPIViewCreateAPIViewUpdateAPIViewDestroyAPIViewの実装例です。それぞれのクラスは、異なるデータ操作を行うために使用されます。

from rest_framework.generics import RetrieveAPIView, CreateAPIView, UpdateAPIView, DestroyAPIView
from .models import MyModel
from .serializers import MyModelSerializer

class MyModelRetrieveAPIView(RetrieveAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

    # データの取得ロジックを実装するためのメソッド
    def get(self, request, *args, **kwargs):
        # データを取得してシリアライズ
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

class MyModelCreateAPIView(CreateAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

    # データ作成ロジックを実装するためのメソッド
    def create(self, request, *args, **kwargs):
        # リクエストデータをシリアライズして新しいデータを作成
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

class MyModelUpdateAPIView(UpdateAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

    # データ更新ロジックを実装するためのメソッド
    def update(self, request, *args, **kwargs):
        # 更新対象のデータを取得してシリアライズ
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        return Response(serializer.data)

class MyModelDestroyAPIView(DestroyAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

    # データ削除ロジックを実装するためのメソッド
    def destroy(self, request, *args, **kwargs):
        # 削除対象のデータを取得して削除
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)


この記事が気に入ったらサポートをしてみませんか?