Django REST フレームワークで API をビルドする
Django プラグインを有効化
この機能は、Django プラグインに依存しており、PyCharm にはデフォルトでバンドルされて有効になっています。 関連機能が利用できない場合は、プラグインが無効になっていないことを確認してください。
Ctrl+Alt+S を押して設定を開き、 を選択します。
インストール済み タブを開き、 Django プラグインを見つけて、プラグイン名の横にあるチェックボックスを選択します。
このチュートリアルでは、Django REST フレームワークを使用してレンタルプラットフォーム API を作成します。
始める前
次の前提条件が満たされていることを確認してください:
PyCharm バージョン 2023.3 以降を使用しています。 PyCharm をまだお持ちでない場合は、 このページからダウンロードしてください。 PyCharm をインストールするには、プラットフォームに応じた手順に従ってください。
RESTful API の概念に関する一般的な理解。
Python および Django の以前の経験 (Django チュートリアルから始めることができます)。
このチュートリアルは、次の前提で作成されています。
Python 3.11
Django 5.1
Django REST フレームワーク 3.15.2
プロジェクトの設定
に移動するか、 ようこそ画面 の 新規プロジェクト ボタンをクリックします。 新規プロジェクト ダイアログが開きます。
新規プロジェクト ダイアログで、次の操作を行います。
プロジェクトタイプ Django を指定します。
ロケーション フィールドにプロジェクトの場所へのパスを指定し、プロジェクト名として api_tutorial_rental と入力します。
プロジェクトの仮想環境のタイプを選択します (プロジェクト venv を使用します)。
詳細設定 セクションを展開し、アプリケーション名 (rental) を入力します。

作成 をクリックすると、PyCharm がプロジェクトをセットアップし、プロジェクト環境に Django をインストールします。
Django REST フレームワークパッケージは手動でインストールする必要があります。 左側のアイコンをクリックして、 Python パッケージ ツールウィンドウを開きます。 djangorestframework パッケージを検索し、最新バージョンをインストールします。

ここで、 settings.py の
INSTALLED_APPSを更新する必要があります。どこでも検索 (ダブル Shift)を開きます。 シンボル タブに移動し、目的のシンボル(変数、クラスなど)の最初の文字を入力して検索します(例: 「insapp」)。
Enter キー を押して目的のシンボルに移動し、
‘rest_framework’をINSTALLED_APPSに追加します。

シリアライザーの作成
一般的に、シリアライザーは、Django モデルインスタンスまたはクエリセットを他の形式 (通常は JSON または XML) に「変換」して、HTTP 応答の本文で送信できるようにするために使用されます。 シリアライザーは、HTTP 要求からのテキストデータが解析され、検証され、モデルインスタンスに変換されるときに、逆シリアル化も提供します。
シリアル化とデシリアル化のプロセスはどの API にとっても重要であり、Django REST フレームワークはそれを完全に引き継ぐことができます。 ModelSerializer クラスのおかげで、わずか 2 行のコードで任意のモデルのシリアライザーを生成できます。
モデルベースのシリアライザーの作成
どこでも検索 または Project ツールウィンドウ (Alt+1) を使用して レンタル / モデル .py を開き、次のコードをエディターにコピーします。
from django.db import models SIZE_CHOICES = [ ('ST', 'Studio'), ('1BR', '1 bedroom'), ('2BR', '2 bedrooms'), ('3BR', '3 bedrooms'), ('MBR', '3+ bedrooms'), ] TYPE_CHOICES = [ ('H', 'house'), ('APT', 'apartment'), ] class Offer(models.Model): created = models.DateTimeField(auto_now_add=True) address = models.CharField(max_length=100, blank=True, default='') size = models.CharField(choices=SIZE_CHOICES, default='1BR', max_length=100) type = models.CharField(choices=TYPE_CHOICES, default='APT', max_length=100) price = models.PositiveIntegerField(default=0) sharing = models.BooleanField(default=False) text = models.TextField(default='') class Meta: ordering = ['created']Offerモデルのすべてのフィールドにはデフォルトがあるため、フィールド値を指定せずにインスタンスを作成できます。 さらに、sizeフィールドとtypeフィールドの選択肢も用意しました。それでは、移行を実行しましょう。 PyCharm の manage.py コンソール(Ctrl+Alt+R )を開き、次のコマンドを実行します:
makemigrations- モデルをスキャンして変更を検出し、データベース構造の変更を反映する新しい移行ファイルを作成します。migrate- 移行ファイルをデータベースに適用し、モデルの現在の状態に合わせてスキーマを更新します。

次に、 レンタル ディレクトリに serializers.py を作成する必要があります。 Project ツールウィンドウ (Alt+1) でディレクトリを右クリックし、 に移動して、ファイル名として「serializers」を指定します。

新しく作成されたファイルがエディターで開きます。 次のコードを入力します。
from rest_framework import serializers from rental.models import Offer class OfferSerializer(serializers.ModelSerializer): class Meta: model = Offer fields = ['id', 'address', 'size', 'type', 'price', 'sharing', 'text']
ご覧のとおり、
OfferSerializerは Django REST フレームワークによって提供されるModelSerializerを継承し、わずか 2 行のコードで定義されています。 6 行目ではベースモデル (2 行目の レンタル / モデル からインポート) を指定し、7 行目にはシリアル化するモデルフィールドのリストが含まれています。
シリアライザーを使用してデータを保存する
シリアライザーを使用してデータベースにデータを追加してみましょう。
左側の対応するアイコンをクリックして Python コンソールを開き、次のコードを実行します。
from rental.models import Offer offer = Offer(text='A cozy space in "loft" style.\nPerfect for young couples') offer.save() offer = Offer(text='A warm house for a big family') offer.save()
Offerモデルのインスタンスを 2 つ作成し、組み込みのsave()メソッドを使用してデータベースに保存しました。それでは、データベースを開いてみましょう。 プロジェクトには db.sqlite3 が含まれており、これは Project ツールウィンドウから、または どこでも検索 を使用して開くことができます。 データベースを初めて開くと、PyCharm はそれをプロジェクトデータソースとして登録します。 データソースおよびドライバー ウィンドウが開きます。
接続のテスト をクリックしてください。 データベースドライバーをインストール、更新、切り替える必要があるという警告が表示された場合は、必要なアクションを実行します。 次に、 OK をクリックして、プロジェクトへのデータソースの追加を完了します。

データベース ツールウィンドウが開いたら、 rental_offer テーブルが表示されるまで db データソースの構造を展開します。

クリックすると、エディターでその内容を参照できます。

ご覧のとおり、データベーステーブルには現在 2 つのレコードがあります。
text以外のどのフィールドにも値を指定していないため、モデル定義の既定値が使用されています。
REST API ロジックの提供
関数ベースのビューの作成
ここで、API が受信したリクエストに基づいてレンタルオファーを自動的に追加できるようにしたいと考えています。
レンタル / ビュー .py で API のロジック作成を始めましょう。 ファイルを開き、次のコードを入力します:
from rest_framework import status from rest_framework.decorators import api_view from rest_framework.response import Response from rental.models import Offer from rental.serializers import OfferSerializer @api_view(['GET', 'POST']) def offer_list(request): if request.method == 'GET': offers = Offer.objects.all() serializer = OfferSerializer(offers, many=True) return Response(serializer.data) elif request.method == 'POST': serializer = OfferSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
offer_listという関数ベースのビューを追加しました。 これは、利用可能なレンタルオファーに関する情報を提供するだけでなく、データベースに新しいオファーを追加するために使用されます。 内容は次のとおりです。@api_view(7 行目) は、関数ベースのビュー用の Django REST フレームワークデコレータです。GETとPOSTは、このビューで受け入れられるメソッドです。リクエストメソッドが
GETの場合、データベース内のすべてのオファーを含むクエリセットが作成され (行 10)、シリアル化されます (行 11)。 この場合、レスポンスの本文には、利用可能なすべてのオファーに関するデータが JSON 形式で含まれます。 レスポンスは、デフォルトのステータスコード (200 OK) とともに送信されます。リクエストメソッドが
POSTの場合、リクエストからのデータをデシリアライズするためにOfferSerializerが使用されます (行 14)。 データが正常に検証された場合 (行 15)、データはデータベースに保存されます (行 16)。 レスポンスには保存されたデータが含まれ、ステータスコードは201 Createdになります (行 17)。検証に失敗した場合、API はステータス
400 Bad Requestとともにエラー情報を返します。
特定のオファーの情報を取得したり、その情報を編集したり、オファーをデータベースから削除したりできると便利です。 別のビューを追加して
offer_detailと名付けましょう:@api_view(['GET', 'PUT', 'DELETE']) def offer_detail(request, pk): try: offer = Offer.objects.get(pk=pk) except Offer.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) if request.method == 'GET': serializer = OfferSerializer(offer) return Response(serializer.data) elif request.method == 'PUT': serializer = OfferSerializer(offer, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) elif request.method == 'DELETE': offer.delete() return Response(status=status.HTTP_204_NO_CONTENT)
このビューは 3 つのメソッド (
GET、PUT、DELETE) を受け入れ、次のように動作します。まず、
pkパラメーターで指定された ID のオファーがデータベースに存在するかどうかを確認します (23 行目)。 存在しない場合は、404 Not Foundが返されます。GETリクエストの場合、API はオファーデータ (行 28) をシリアル化し、レスポンス本文で返します。PUTリクエストの場合、API はデータベースからのオファーデータをシリアル化し、リクエスト本体のデータとマージします (行 32)。 検証が成功した場合 (行 33)、更新されたオファーがデータベースに保存され (行 34)、レスポンス本体で返されます (行 35)。 それ以外の場合は、400 Bad Requestステータスとともにエラー情報が返されます。最後に、
DELETEリクエストの場合、API はオファーを削除し、204 No Contentを返します。
API のロジックを定義したため、API を使用する前に残っているのは 1 つのステップだけです。 API エンドポイントとも呼ばれる Django URL を定義する必要があります。
API エンドポイントの定義とテスト
まず、アプリディレクトリに urls.py を作成し、次のコードを入力します。
from django.urls import path from rental import views urlpatterns = [ path('offers/', views.offer_list), path('offers/<int:pk>/', views.offer_detail), ]2 つのビューに 2 つのエンドポイントを定義しました。
既存のプロジェクトの urls.py ファイルに レンタル /urls.py を含めます。
from django.urls import path,include urlpatterns = [ path('', include('rental.urls')), ]エンドポイント ツールウィンドウを開きましょう。 まだ使用したことがない場合は、左側のメニューにあります。

ツールウィンドウには、使用可能なすべてのエンドポイントとメソッドが表示されます。

API をテストする前に、Django サーバーが実行中であることを確認してください。 プロジェクトの作成時に、PyCharm は実行構成を自動的に設定します。 ウィンドウヘッダーの 実行 ウィジェットから起動するだけです。 開いた 実行 ツールウィンドウのサーバーアドレス (通常は localhost) とポート番号をメモします。

エンドポイント ツールウィンドウに戻りましょう。 リストから /offers/ を選択し、下部の HTTP クライアント タブに切り替えます。 必要に応じてポート番号を編集し、 リクエストの送信 をクリックします。

PyCharm はリクエストを実行し、レスポンス本文をファイルに保存します。 上にスクロールしてレスポンスを調べるか、リンクをクリックしてエディターでファイルを開くことができます。

2 番目のオファー (
DELETE http://localhost:8000/offers/2/) を削除するためにDELETEリクエストを送信し、次に利用可能なオファーのリスト (GET http://localhost:8000/offers/) の別のリクエストを送信します。 これで、利用可能なオファーは 1 つだけになります。
Django REST フレームワークのもう 1 つの機能は、ブラウズ可能な API です。 ブラウザーで http://localhost:8000/offers/ (必要に応じてポート番号を編集) を開くと、利用可能なオファーのリストを表示したり、新しいオファーを追加したりできるページが表示されます。

汎用クラスベースのビューの実装
Django REST フレームワークの素晴らしい機能について語るとき、汎用クラスベースのビューについてメンションしないわけにはいきません。
これらを使用して レンタル / ビュー .py のコードを書き直してみましょう。
from rest_framework import generics from rental.models import Offer from rental.serializers import OfferSerializer class OfferList(generics.ListCreateAPIView): queryset = Offer.objects.all() serializer_class = OfferSerializer class OfferDetails(generics.RetrieveUpdateDestroyAPIView): queryset = Offer.objects.all() serializer_class = OfferSerializerこれで、各ビューのコードは 3 行だけになりました。 継承する適切なジェネリクスクラスを選択することだけに注意すれば済みます。
フィーチャベースのビューはもう使用していないため、 レンタル /urls.py を更新する必要があります。
urlpatterns = [ path('offers/', views.OfferList.as_view()), path('offers/<int:pk>/', views.OfferDetails.as_view()), ]API 検証がどのように機能するかを確認するために、無効なデータを送信してみましょう。
エンドポイント ツールウィンドウに移動します。 これで、汎用ビューから取得される追加の
OPTIONSおよびPATCHメソッドが存在します。 エンドポイントのリストから /offers/ を選択し、 エディターで開く をクリックします。 PyCharm は .http ファイルを作成し、エンドポイントをそのファイルにコピーします。 JSON 形式でリクエスト本文を指定して、リクエストを送信します。POST http://localhost:8000/offers/ Content-Type: application/json { "address": "", "size": "8BR", "type": "H", "price": 1000000, "sharing": true, "text": "A spacious villa for a large family." }
開いた サービス ツールウィンドウで、応答に
400 Bad Requestステータスがあることがわかります。 リンクをクリックして、応答を含む JSON ファイルを開きます。
ご覧のとおり、
sizeに間違った値を指定したため、オファーは追加されていません。Offerモデルによれば、ベッドルームが 3 つ以上ある場合はMBRを使用する必要があります。 リクエストを編集して再度送信してみましょう。
認証と権限の有効化
現時点では、エンドポイントアドレスを知っている人なら誰でもオファーを追加、編集、削除できます。 これは現実の世界では普通の状況ではありません。 通常は、API で誰が何を実行できるかを制御したいものです。 これは、認証と権限を実装することで実現できます。
ユーザーの紹介
まず、ユーザーの概念を導入する必要があります。 まず、
Offerモデルにauthorフィールドを追加してみましょう。author = models.ForeignKey('auth.User', related_name='offers', on_delete=models.CASCADE)このフィールドは
ForeignKey型であり、オファーとそれを作成するユーザー間の関係を表すために使用されます。モデルを更新したため、データベースをリセットし、その中に rental_offer テーブルを再作成して、
authorフィールドを追加する必要があります。 これを実現するには、次の手順を実行します。manage.py コンソール (Ctrl+Alt+R) を開き、次のコマンドを 1 つずつ実行します。
> flush > migrate rental zeroレンタル / 移行 ディレクトリで、すべての移行を削除し、 __init__.py のみを残します。
次に、 manage.py コンソールで続行します。
> makemigrations > migrate
続行する準備ができていることを確認するには、 データベース ツールウィンドウに移動して rental_offer テーブルを開きます。 author_id 列 があるはずです。
次に レンタル / シリアライザー .py を開いて
UserSerializerを追加します。 Django の組み込み認証システムを使用するため、既存のUserモデルをインポートし、新たに追加したauthorフィールドに対応するようにOfferSerializerを更新します:from rest_framework import serializers from rental.models import Offer from django.contrib.auth.models import User class OfferSerializer(serializers.ModelSerializer): author = serializers.ReadOnlyField(source='author.username') class Meta: model = Offer fields = ['id', 'address', 'size', 'type', 'price', 'sharing', 'text', 'author'] class UserSerializer(serializers.ModelSerializer): offers = serializers.PrimaryKeyRelatedField(many=True, queryset=Offer.objects.all()) class Meta: model = User fields = ['id', 'username', 'offers']
レンタル / ビュー .py に2つの新しいビューも定義する必要があります。1つは全ユーザーリスト用、もう1つはユーザー詳細用です。 ここでも
Userモデルをインポートし、新しく作成したUserSerializerも serializers.py からインポートしてください。 また、OfferListクラスを更新して、デフォルトのperform_create()メソッドをオーバーライドし、オファー作成時に追加のauthorフィールドが渡されるようにします。from rest_framework import generics from rental.models import Offer from rental.serializers import OfferSerializer, UserSerializer from django.contrib.auth.models import User class OfferList(generics.ListCreateAPIView): queryset = Offer.objects.all() serializer_class = OfferSerializer def perform_create(self, serializer): serializer.save(author=self.request.user) class OfferDetails(generics.RetrieveUpdateDestroyAPIView): queryset = Offer.objects.all() serializer_class = OfferSerializer class UserList(generics.ListAPIView): queryset = User.objects.all() serializer_class = UserSerializer class UserDetails(generics.RetrieveAPIView): queryset = User.objects.all() serializer_class = UserSerializer
ユーザー用の以下のエンドポイントを レンタル /urls.py に追加します:
from django.urls import path from rental import views urlpatterns = [ path('offers/', views.OfferList.as_view()), path('offers/<int:pk>/', views.OfferDetails.as_view()), path('users/', views.UserList.as_view()), path('users/<int:pk>/', views.UserDetails.as_view()), ]
認証を必須にする
ここで、認証されたユーザーだけが API を通じてオファーを追加できるようにする必要があります。
OfferListとOfferDetailsの両方のビューで権限を設定するために、次のプロパティを追加します。 認証済みユーザーはオファーの追加・編集ができ、それ以外は閲覧のみ可能です:from rest_framework import generics from rental.models import Offer from rental.serializers import OfferSerializer, UserSerializer from django.contrib.auth.models import User from rest_framework import permissions class OfferList(generics.ListCreateAPIView): queryset = Offer.objects.all() serializer_class = OfferSerializer permission_classes = [permissions.IsAuthenticatedOrReadOnly] def perform_create(self, serializer): serializer.save(author=self.request.user) class OfferDetails(generics.RetrieveUpdateDestroyAPIView): queryset = Offer.objects.all() serializer_class = OfferSerializer permission_classes = [permissions.IsAuthenticatedOrReadOnly] class UserList(generics.ListAPIView): queryset = User.objects.all() serializer_class = UserSerializer class UserDetails(generics.RetrieveAPIView): queryset = User.objects.all() serializer_class = UserSerializer
期待どおりに動作することを確認するために、認証なしで
POSTリクエストを実行してみましょう。POST http://localhost:8000/offers/ Content-Type: application/json { "address": "", "size": "1BR", "type": "APT", "price": 350000, "sharing": false, "text": "A small modern flat. Central location." }403 Forbidden応答が返されるはずです。
ユーザーを作成しましょう。 manage.py コンソールに移動し、
createsuperuserコマンドを実行します。 指定したユーザー名とパスワードを覚えておいてください。次のステップに進む前に、ユーザー名とパスワードをコロンでつないだ Base64 エンコード文字列が必要です。 例えば、パスワード「pass123」で「admin」を作成しています(あくまでも例であり、実際にはもっと強力なパスワードを使用してください)。 Python コンソールを開き、'admin:pass123' をご自身の資格情報に置き換えて、次を実行してください:
>>> import base64 >>> base64.b64encode(b'admin:pass123')
ここで、
Authorizationヘッダーを使用して同じリクエストを実行してみましょう。POST http://localhost:8000/offers/ Authorization: Basic YWRtaW46cGFzczEyMw== Content-Type: application/json { "address": "", "size": "1BR", "type": "APT", "price": 350000, "sharing": false, "text": "A small modern flat. Central location." }201 Created応答が返されるはずです。
権限の詳細
現時点では、認証されたユーザーであれば誰でもオファーを編集できます。 オファーを作成者だけが編集できるように権限を設定しましょう。
レンタル / 権限 .py を作成し、次のコードを入力します。
from rest_framework import permissions class IsAuthorOrReadOnly(permissions.BasePermission): def has_object_permission(self, request, view, obj): return request.method in permissions.SAFE_METHODS or obj.author == request.userIsAuthorOrReadOnlyクラスは、Django REST フレームワークのBasePermissionクラスのサブクラスです。 リクエストメソッドがSAFE_METHODS(GET、HEAD、OPTIONS) のいずれかである場合、権限は無条件に付与されます。 それ以外の場合、権限を取得するには、リクエスト元のユーザーがオファーの作成者である必要があります。views.py に移動し、新規作成したパーミッションをインポートして、
OfferDetailsのpermission_classesを更新します:from rest_framework import generics from rental.models import Offer from rental.serializers import OfferSerializer, UserSerializer from django.contrib.auth.models import User from rest_framework import permissions from rental.permissions import IsAuthorOrReadOnly class OfferList(generics.ListCreateAPIView): queryset = Offer.objects.all() serializer_class = OfferSerializer permission_classes = [permissions.IsAuthenticatedOrReadOnly] def perform_create(self, serializer): serializer.save(author=self.request.user) class OfferDetails(generics.RetrieveUpdateDestroyAPIView): queryset = Offer.objects.all() serializer_class = OfferSerializer permission_classes = [ permissions.IsAuthenticatedOrReadOnly, IsAuthorOrReadOnly ] class UserList(generics.ListAPIView): queryset = User.objects.all() serializer_class = UserSerializer class UserDetails(generics.RetrieveAPIView): queryset = User.objects.all() serializer_class = UserSerializer
次に、 manage.py コンソールで
createsuperuserを実行して別のユーザーを作成します (「jetbrains:jet123」を使用します)。 次に下記のリクエストを送信して、ID 1 (adminユーザーによって作成) のオファーを更新します。PUT http://localhost:8000/offers/1/ Authorization: Basic amV0YnJhaW5zOmpldDEyMw== Content-Type: application/json {"text":"A small modern flat. Very central location."}応答の詳細には「このアクションを実行する権限がありません」という内容の
403 Forbiddenが表示されます。
次に、管理者の資格情報を使用して同じ操作を試します。
PUT http://localhost:8000/offers/1/ Authorization: Basic YWRtaW46cGFzczEyMw== Content-Type: application/json {"text":"A small modern flat. Very central location."}200 OKを取得する必要があります。ブラウズ可能な API に認証があるかどうかを確認しましょう。 ブラウザーで http://localhost:8000/offers/1/ (必要に応じてポート番号を編集) を開きます。
POSTメソッドに関連付けられたフォームはなくなり、DELETEボタンもなくなりました。 このような操作にブラウズ可能な API を使用できるようにするには、ログインページを有効にする必要があります。プロジェクトの urls.py に移動し、次のように更新します:
from django.urls import path, include urlpatterns = [ path('', include('rental.urls')), path('api-auth/', include('rest_framework.urls')), ]
次に、ブラウザーでページを更新します。 右上隅に ログイン が表示されます。 それをクリックし、以前に作成したユーザーの 1 人の資格情報を入力して、オファーに対するアクションを実行できるようにします。
結論
このチュートリアルを完了することで、Django REST フレームワークの以下の機能を実装できるようになりました:
モデルに基づいてシリアライザーを作成するための
ModelSerializerAPI ロジックを簡潔かつ慣用的な方法で記述するための汎用クラスベースのビュー。
利用可能なエンドポイントとデータを簡単に視覚化するための参照可能な API。
ユーザー権限を設定するための Django 認証システム。