前回は、シリアライズについて学びました。
本日は、Django Rest FrameworkのAPI View(@api_view)について学びます。
前回
API Viewについて
前回は、Serializerクラスを通じて、シリアライズ/デシリアライズのやり方をみてきました。
今回、Django REST FrameworkのAPI Viewを使ってシリアライズ/デシリアライズされたデータの受け渡し方法をみていきましょう。
API Viewを使うために、Django REST Frameworkでは、2つのラッパーを提供しています。
- @api_viewデコレータ – 関数ベースのAPI View
- ApiViewクラス – クラスベースのAPI View
本記事では、@api_viewについて扱います。
ファイルの準備
API Viewの処理を書き出すファイルを準備しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
touch selfnote_api/news/api/views.py touch selfnote_api/news/api/urls.py selfnote_api/ ├── db.sqlite3 ├── manage.py ├── news │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-37.pyc │ │ ├── admin.cpython-37.pyc │ │ └── models.cpython-37.pyc │ ├── admin.py │ ├── api │ │ ├── serializers.py │ │ └── views.py # New │ │ └── urls.py # New │ ├── apps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── __init__.py │ ├── models.py │ ├── tests.py │ └── views.py └── selfnote_api ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py |
Article Listの実装 ~@api_view~
@api_viewデコレータを使って、Article Listを実装します。
Viewの設定 – GET編
ユーザーリクエストをさばくAPI VIewを実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# news/api/views.py from rest_framework import status from rest_framework.decorators import api_view from rest_framework.response import Response from news.models import Article from news.api.serializers import ArticleSerializer @api_view(["GET"]) def article_list_create_api_view(request): if request.method == "GET": articles = Article.objects.filter(active=True) serializer = ArticleSerializer(articles, many=True) return Response(serializer.data) |
上記ではGETリクエストされた時に、DBに保存されている全てのArticleデータを取得し、そのデータをシリアライズ後、リクエスト元に返却しています。
また、データを取得する条件として、Articleが有効(active=True)なデータを取得しています。
URLディスパッチャ
リクエスト先のURLを実装します。
まずは、newsアプリ配下のurls.pyに以下の実装をしてください。
1 2 3 4 5 6 7 8 |
# news/api/urls.py from django.urls import path from news.api.views import article_list_create_api_view urlpatterns = [ path("articles/", article_list_create_api_view, name="article-list"), ] |
「XXXX/articles」にリクエストを送った時に、article_list_create_api_viewへ処理依頼をするように実装しました。
次に、selfnote_api配下のurls.pyも変更してください。
1 2 3 4 5 6 7 8 9 |
# selfnote_api/urls.py from django.contrib import admin from django.urls import path, include # new urlpatterns = [ path('admin/', admin.site.urls), path("api/", include("news.api.urls")), # new ] |
これで、「localhost:8000/api/articles」にアクセスすれば、DBに保存されたArticleの一覧が表示できるはずです。
動作確認 – GET編
開発サーバーを起動します。
1 |
python manage.py runserver |
「localhost:8000/api/articles」にアクセスしましょう。

OKですね。
many=Trueオプションについて
補足ですが、ArticleSerializerの「many=True」オプションを外すと、以下のようになります。

AttributeError: Got AttributeError when attempting to get a value for field
author
on serializerArticleSerializer
.
The serializer field might be named incorrectly and not match any attribute or key on theQuerySet
instance.
Original exception text was: ‘QuerySet’ object has no attribute ‘author’.
これはデータの渡し方に問題があります。
もともとArticleSerializerクラスには「単一のデータ」しか渡せません。
しかし、以下のようにfilterメソッドを使ってデータを取得するとリスト形式でデータが返却されてしまいます。
1 |
articles = Article.objects.filter(active=True) |
リスト形式など”複数のデータをシリアライズクラスに渡したい“場合は、many=Trueオプションをつけましょう。
ちなみに、以下のようにすれば、エラーは発生しませんでした。
1 2 3 4 5 6 |
@api_view(["GET"]) def article_list_create_api_view(request): if request.method == "GET": articles = Article.objects.filter(active=True)[0]# データを1つに絞る serializer = ArticleSerializer(articles) return Response(serializer.data) |
Viewの設定 – POST編
続いて、POSTを実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@api_view(["GET", "POST"]) def article_list_create_api_view(request): if request.method == "GET": articles = Article.objects.filter(active=True) serializer = ArticleSerializer(articles, many=True) return Response(serializer.data) elif request.method == "POST": serializer = ArticleSerializer(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) |
POSTでは、リクエスト時に受け取ったデータの検証を行なった後、DB登録する処理を書いています。
ちなみに、saveメソッドを呼ぶとArticleSerializerクラスに実装されているcreate関数が自動的に呼び出されるようになっています。
動作確認 – POST編
ブラウザをリダイレクトすると以下のフォームが表示されると思います。

ContentにJSON形式のデータを入れて、DBに登録されるか確認してみましょう。
1 2 3 4 5 6 7 8 |
{ "author": "selfnote", "title": "first post", "body": "this is a first post", "location": "tokyo", "publication_date": "2020-05-22", "active": true } |


OKですね。
Article Detailの実装 ~ @api_view~
Article Listの実装が完了したので、今度はArticleの詳細を表示するAPI Viewを実装しましょう。
Viewの設定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# news/api/views.py from rest_framework import status from rest_framework.decorators import api_view from rest_framework.response import Response from news.models import Article from news.api.serializers import ArticleSerializer ... @api_view(["GET", "PUT", "DELETE"]) def article_detail_api_view(request, pk): err_msg = { "error": { "code": 404, "message": "Article not found", }} try: article = Article.objects.get(id=pk) except Article.DoesNotExist: return Response(err_msg, status=status.HTTP_404_NOT_FOUND) if request.method == "GET": serializer = ArticleSerializer(article) return Response(serializer.data) if request.method == "PUT": serializer = ArticleSerializer(article, 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": article.delete() return Response(status=status.HTTP_204_NO_CONTENT) |
今回は、GET, PUT, DELETEメソッドを使います。
GETでは、指定したID(pk)の記事を取得し、PUTでは記事の更新、DELETEでは記事の削除をそれぞれ担当します。
article_detail_api_view関数の引数に指定しているpkは、ArticleのIDを示しており、URLディスパッチャ(次に設定する)のpkをここで受け取ることができます。
URLディスパッチャ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# news/api/urls.py from django.urls import path from news.api.views import ( article_list_create_api_view, article_detail_api_view, ) urlpatterns = [ path("articles/", article_list_create_api_view, name="article-list"), path("articles/<int:pk>", article_detail_api_view, name="article-detail"), ] |
“article/<int:pk>”のpkと、article_detail_api_view (request, pk)のpkの文字列は完全一致でなければなりません。
動作確認
動作確認をしてみましょう。
先ほど、id(pk)が4のArticleを作成したので、以下のURLにアクセスします。
「http://localhost:8000/api/articles/4」

無事に詳細ページが表示されました。
記事の更新をしてみましょう。Content欄にアップデートしたいデータを書き込んで、PUTボタンを押下します。
1 2 3 4 5 6 7 8 |
{ "author": "another selfnote", "title": "Great post", "body": "Great Post!", "location": "tokyo", "publication_date": "2020-05-23", "active": true } |


無事に更新されましたね。
最後に、ページ上部のDELETEボタンを押下して、削除機能を試してみましょう。

DELETEも問題ないですね。
次回
次回は、もう一つのAPI ViewラッパーであるAPI Viewクラスについて学んでいきましょう!
関連
こちらもどうぞ
Djangoおすすめ書籍
Djangoを学ぶなら以下の書籍がオススメです。
緑 -> 赤 -> 紫の順でやればOKです。読みやすい英語で書かれているので、英語力もついでに上がるかもしれません^^
コメントを残す
コメントを投稿するにはログインしてください。