60
67

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Django Rest Framework で RESTful な APIを作成する

Last updated at Posted at 2020-01-03

概要

 この記事は初心者の自分がRESTful なAPIとswiftでiPhone向けのクーポン配信サービスを開発した手順を順番に記事にしています。技術要素を1つずつ調べながら実装したため、とても遠回りな実装となっています。

 前回のSwiftのTableViewCellを使ってTableViewを自由にカスタマイズで、データベースで管理するクーポン情報をAPIを通してアプリが取得し、リスト形式で表示するところまで作成しました。

 次はこのAPIをRESTfulなAPIに改造します。改造にあたりコードを大幅に変更するため、一旦GETで全てのクーポン情報をレスポンスするだけのAPIを実装し、その後にリクエストに応じたクーポン情報をレスポンスするよう修正を加えていきます。

参考

環境

Mac OS 10.15
VSCode 1.39.2
pipenv 2018.11.26
Python 3.7.4
Django 2.2.6

手順

  • Django Rest Framework をインストールする
  • Django Rest Framework を取り込む
  • Serializerを定義する
  • View.pyを改造する
  • URL_patternを定義する
  • curl コマンドを使って動作確認をする

Django Rest Framework をインストールする

自分はpipenvでpythonのプロジェクト(仮想環境)を作っているので、そこに django rest framework をインストールします。pipenvのシェルに入り、インストールのコマンドを実行します。

$ pipenv shell  #シェルに入る
$ pipenv install djangorestframework # インストール実行

インストール中のターミナル...
install-django-rest-framework.png

インストール完了後にPipfileの中を見ると、[packages]djangorestframeworkが追加されています。


[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
django = "*"
djangorestframework = "*"

[requires]
python_version = "3.7"

Django Rest Framework を取り込む

プロジェクト名のディレクトリ配下のsetting.pyINSTALLED_APPS = { に インストールした rest_framework を追加するだけです。


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'coupon',
    'rest_framework', # 追加
]

これで Django Rest Framework を使う準備が完了しました。

Serializerを定義する

 Rest Framework を使うには Serializer というモジュールが必要です。アプリのディレクトリ配下に自分で Serializer のファイルを作り実装します。

下記のように実装しました。

coupon/serializer.py

from rest_framework import serializers # Django Rest Frameworkをインポート
from .models import Coupon # models.py のcouponクラスをインポート

class CouponSerializer(serializers.ModelSerializer):
    class Meta:
        model = Coupon # 扱う対象のモデル名を設定する
        fields = '__all__'

上のコードで、fieldsはレスポンスしたいモデルフィールド(ここではクーポン情報)を指定します。特に指定せず全ての項目をレスポンスする場合は'__all__'とします。

View.pyを改造する

views.pyを Django Rest Framework を使った場合に合わせて改造します。

  • rest_framework の viewsets と filters をインポート
  • 上で定義した serializer の CouponSerializer をインポート
  • 全てのクーポン情報をレスポンスする queryset に変更
  • rest_framework を使うと データをjson 形式にしたり dump したり、HTTPでレスポンスする処理は自動でやってくれるようなので、それらの不要になった処理を削除
  • 上で定義した serializer.pyのCouponSerializer を呼ぶ。

コードは下記のようになります。非常にシンプルになりました。

views.py
from django.shortcuts import render
from .models import Coupon
from rest_framework import viewsets, filters
from .serializer import CouponSerializer


class CouponViewSet(viewsets.ModelViewSet):
    queryset = Coupon.objects.all() # 全てのデータを取得
    serializer_class = CouponSerializer

URL_patternを定義する

 ami_coupon_api/urls.pyと、coupon/urls.pyを編集します。実感としてはcoupon/urls.pyから編集した方が良さそうです。

coupon/urls.pyの編集内容は下記の通りです。

  • rest_framework の routers をインポート
  • views.py で定義した、CouponViewSet をインポート
  • router を定義して、router.register に URLとそのURLがリクエストされた時に呼び出すview.pyのクラス(ここでは CouponViewSet)を紐付ける。
coupon/urls.py
from django.urls import path
from . import views
from rest_framework import routers
from .views import CouponViewSet

router = routers.DefaultRouter()
router.register(r'coupons', CouponViewSet)

上記で、r’coupons’ の ‘coupons’ の部分が リクエストURLの後ろに付きます。

ami_coupon_api/urls.pyの編集内容は下記の通りです。

  • django.conf.urls の url と include をインポート
  • coupon/urls.py で定義した router を coupon_routerとしてインポート
  • urlpatternsにURLと呼び出し先を定義
  • URLが admin/ の場合は、django の コンソールへ進むように設定
  • api/ の場合は、router で設定したオブジェクトへ進むように設定
ami_coupon_api/urls.py
from django.contrib import admin
from django.urls import path,include
from django.conf.urls import url, include
from coupon.urls import router as coupon_router

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/', include(coupon_router.urls)),
]

curl コマンドを使って動作確認をする

 新しいターミナルを開いて GET、POST、PUT のリクエストを試してみます。リクエストの書き方は下記の通りです。-X はHTTPメソッド(GET、POST、PUT など)を指定するためのオプションです。なお、GETとPOST は指定しなくても実行可能でした。

$ curl -X [HTTPメソッド] [URL] [リクエストパラメータ]

GETを試します。リクエストパラメータは付けていません。

$ curl -X GET http://127.0.0.1:8000/api/coupons/

こんなjsonが返ってきました。


[{"id":1,"code":"0001","benefit":"お会計から1,000円割引","explanation":"5,000円以上ご利用のお客様限定。他クーポンとの併用不可。","store":"全店","start":"2019-10-01","deadline":"2019-12-31","status":true},{"id":2,"code":"0002","benefit":"お会計を10%オフ!","explanation":"他クーポンとの併用不可","store":"有楽町店","start":"2019-10-01","deadline":"2019-12-31","status":true},{"id":3,"code":"0003","benefit":"【ハロウィン限定】仮装して来店すると30%オフ","explanation":"全身の50%以上を仮装されているお客様限定(判断はスタッフの感覚とさせて頂きます)。他クーポンとの併用不可","store":"神田店","start":"2019-10-31","deadline":"2019-10-31","status":true},{"id":4,"code":"0004","benefit":"【9月限定】お月見団子サービス","explanation":"ご希望のお客様に月見団子をプレゼント! 他クーポンとの併用可能です!","store":"全店","start":"2019-09-01","deadline":"2019-09-30","status":true},{"id":5,"code":"0005","benefit":"【雨の日限定】お会計から15%オフ","explanation":"クーポンが配信された時だけ利用可能です。他クーポンとの併用不可","store":"全店","start":"2019-10-01","deadline":"2019-12-31","status":false},{"id":6,"code":"0006","benefit":"【日曜日限定】乾杯テキーラサービス","explanation":"テキーラを人数分サービスします。他クーポンとの併用可。","store":"神田店","start":"2019-11-03","deadline":"2019-12-01","status":true}]


POSTを試します。

curl -X POST http://127.0.0.1:8000/api/coupons/ -d "code=0007" -d "benefit=お会計から19%引き" -d "explanation=12月29日~12月31日限定。 " -d "store=神田店" -d "start=2019-12-29" -d "deadline=2019-12-31" -d "status=true"

上手くいくとPOSTしたデータがjsonで返って来ます。


{"id":7,"code":"0007","benefit":"お会計から19%引き","explanation":"12月29日~12月31日限定。","store":"神田店","start":"2019-12-29","deadline":"2019-12-31","status":true}


PUTを試します。
PUTの時はHTTPメソッドを指定する必要があります。それより重要なのは、URLにテーブルのプライマリキーを指定する必要があります。couponモデルでは”id”がプライマリキーになっているので、URLの末尾に上書きしたいデータのid(ここでは 7 )を指定します。

curl -X PUT http://127.0.0.1:8000/api/coupons/7/ -d "code=0007" -d "benefit=お会計から19%引き" -d "explanation=12月29日~12月31日限定。他のクーポンとの併用不可 " -d "store=神田店" -d "start=2019-12-29" -d "deadline=2019-12-31" -d "status=true"

上手くいくと上書きされたデータがjsonで返って来ます。


{"id":7,"code":"0007","benefit":"お会計から19%引き","explanation":"12月29日~12月31日限定。他のクーポンとの併用不可","store":"神田店","start":"2019-12-29","deadline":"2019-12-31","status":true}


DELETEを試します。
先ほどPOSTしたリクエストをもう一度実行し、id=8のクーポンを作ります。GETリクエストかDjangoサーバのコンソールでid=8のクーポンが追加されたことを確認してください。

次に、下記のリクエストでid=8のクーポンを削除します。PUTと同様に削除対象のクーポンのプライマリキーの指定が必要です。

curl -X DELETE http://127.0.0.1:8000/api/coupons/8/

上手くいくと何も返って来ません。
GETリクエストかDjangoサーバのコンソールでid=8のクーポンが削除されたことを確認してください。

ここまでで基本的なRest Framework が出来ました。ここから 条件に合うクーポンのみをGETするためのフィルタや認証機能を追加していきます。

60
67
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
60
67

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?