LoginSignup
26
29

More than 5 years have passed since last update.

Django REST frameworkでAPIを作ってみた

Posted at

はじめに

Vue.js+Django REST frameworkを試す前段階として、まずDjango REST frameworkでAPIを実装します。

開発環境

$ python --version
Python 3.5.1

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.2
BuildVersion:   18C54

プロジェクトの作成

Djangoのプロジェクトを作成します。

# Djagoをインストール
pip install django

# プロジェクトを作成
django-admin startproject myproject

cd myproject

# 起動
python manage.py runserver
ディレクトリ構成
myproject
|_ myproject
|_ manage.py
|_ db.sqlite3

http://localhost:8000/ で画面が表示されているを確認します。

screencapture-localhost-8000-2018-12-17-13_02_38.png

Django REST framework

設定

まずはDjango REST frameworkをインストールします。

pip install django-rest-framework

先程作ったプロジェクトのsettings.pyにrest_frameworkを追加します。

myproject/settings.py
...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
]
...

次にAPIのエンドポイントを設定します。

myproject/urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include, url
from rest_framework import routers

router = routers.DefaultRouter()

urlpatterns = [
    path('admin/', admin.site.urls),
    url('api/', include(router.urls)),
]

ここでDjango REST frameworkが正しく機能しているか確認します。
http://localhost:8000/api で以下の画面が実行されればOKです。

screencapture-localhost-8000-api-2018-12-17-13_02_29.png

アプリケーションの追加

以下のdjango-adminのコマンドを使用してアプリケーションを作ります。

django-admin startapp myapp
ディレクトリ構成
myproject
|_ myproject
   |_ __init__.py
   |_ settings.py
   |_ urls.py
   |_ wsgi.py
|_ myapp
   |_ migrations
   |_ __init__.py
   |_ admin.py
   |_ apps.py
   |_ models.py
   |_ tests.py
   |_ views.py
|_ manage.py
|_ db.sqlite3

アプリケーションをsettings.pyに追加します。

saicoro/settings.py
...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'myapp',
]
...

ここからはガリガリAPIを実装していきます。

Models

myapp/models.py
from django.db import models


class Spot(models.Model):
    # 名前
    name = models.CharField(max_length=50)
    # カテゴリー
    category = models.CharField(max_length=5, blank=True)
    # ジャンル
    genre = models.CharField(max_length=50, blank=True)
    # 都道府県
    address_prefecture = models.CharField(max_length=10, blank=True)
    # 市区町村
    address_city = models.CharField(max_length=10, blank=True)
    # 丁目番地等
    address_street = models.CharField(max_length=100, blank=True)
    # 緯度
    latitude = models.CharField(max_length=50, blank=True)
    # 経度
    longitude = models.CharField(max_length=50, blank=True)
    # 作成日
    created_at = models.DateTimeField(auto_now_add=True)
    # 更新日
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ('created_at',)

以下のコマンドでマイグレーションします。(DBはとりあえずデフォルトのSQLiteのまま)

python manage.py makemigrations
python manage.py migrate

Serializers

myapp/serializers.py
from rest_framework import serializers
from .models import Spot


class SpotListSerializer(serializers.ModelSerializer):
    # 名前
    name = serializers.CharField(max_length=50)
    # カテゴリー
    category = serializers.CharField(max_length=5, allow_blank=True)
    # 都道府県
    address_prefecture = serializers.CharField(max_length=10, allow_blank=True)

    class Meta:
        model = Spot
        fields = ('id', 'name', 'category', 'address_prefecture')


class SpotSerializer(serializers.ModelSerializer):
    # 名前
    name = serializers.CharField(max_length=50)
    # カテゴリー
    category = serializers.CharField(max_length=5, allow_blank=True)
    # ジャンル
    genre = serializers.CharField(max_length=50, allow_blank=True)
    # 都道府県
    address_prefecture = serializers.CharField(max_length=10, allow_blank=True)
    # 市区町村
    address_city = serializers.CharField(max_length=10, allow_blank=True)
    # 丁目番地等
    address_street = serializers.CharField(max_length=100, allow_blank=True)
    # 緯度
    latitude = serializers.CharField(max_length=50, allow_blank=True)
    # 経度
    longitude = serializers.CharField(max_length=50, allow_blank=True)

    class Meta:
        model = Spot
        fields = (
            'name', 'category', 'genre', 'address_prefecture', 'address_city', 'address_street', 'latitude',
            'longitude')

Renderer

Jsonとして取得したいので、その処理をrenderers.pyとしてまとめます。

myapp/renderers.py
import json
from rest_framework.renderers import JSONRenderer


class SpotJSONRenderer(JSONRenderer):
    charset = 'utf-8'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        return json.dumps({
            'spots': data
        })

Views

myapp/views.py
from rest_framework import status
from rest_framework.generics import ListAPIView, RetrieveAPIView
from rest_framework.permissions import AllowAny
from rest_framework.response import Response

from .models import Spot
from .renderers import SpotJSONRenderer
from .serializers import SpotListSerializer, SpotSerializer


class SpotListApiView(ListAPIView):
    model = Spot
    queryset = Spot.objects.all()
    permission_classes = (AllowAny, )
    renderer_classes = (SpotJSONRenderer, )
    serializer_class = SpotListSerializer


class SpotRetrieveApiView(RetrieveAPIView):
    permission_classes = (AllowAny, )
    renderer_classes = (SpotJSONRenderer, )
    serializer_class = SpotSerializer

    def retrieve(self, request, spot_id, *args, **kwargs):
        spot = Spot.objects.get(id=spot_id)
        serializer = self.serializer_class(spot)

        return Response(serializer.data, status=status.HTTP_200_OK)

Urls

apiのエンドポイントを定義します。

myapp/urls.py
from django.conf.urls import url
from .views import SpotListApiView, SpotRetrieveApiView

app_name = 'myapp'
urlpatterns = [
    url(r'^spots/$', SpotListApiView.as_view()),
    url(r'^spots/(?P<spot_id>\w+)/?$', SpotRetrieveApiView.as_view()),
]

myprojectのurls.pyを更新します。

myproject/urls.py
from django.conf.urls import include, url
from django.contrib import admin
from django.urls import path
from rest_framework import routers
from spot import urls

router = routers.DefaultRouter()

urlpatterns = [
    path('admin/', admin.site.urls),
    url('api/', include(router.urls)),
    url('api/', include(urls, namespace='spot')),
]

ここまでの実装を確認するために、データをとりあえず追加します。

pip install ipyhton
python manage.py shell

In [1]: from myapp.models import Spot

In [2]: Spot.objects.create(name="秋葉原UDX", category="オフィス", genre="" , address_prefecture="東京都", address_city="千代田区", address_street="外神田4丁目14-1", latitude="35.700689", longitude="139.772498")                                                  
Out[2]: <Spot: Spot object (1)>

In [3]: Spot.objects.create(name="東京タワー", category="観光地", genre="" , address_prefecture="東京都", address_city="港区", address_street="芝公園4丁目2-8", latitude="35.658816", longitude="139.745476")                                                        
Out[3]: <Spot: Spot object (2)>

In [4]: Spot.objects.create(name="東京スカイツリー", category="観光地", genre="" , address_prefecture="東京都", address_city="墨田区", address_street="押上1丁目1-2", latitude="35.710385", longitude="139.810743")                                                  
Out[4]: <Spot: Spot object (3)>

In [5]: quit()

ブラウザで http://localhost:8000/api/spots/2 を開くと結果が確認できます。

スクリーンショット 2018-12-17 19.20.01.png

終わりに

とりあえずGETだけでしたが、簡単にAPIを実装できたと思います。
みんなDjangoでAPIを実装すべし!

参考資料

Django REST framework
Cute cats web app Django + VueJs— Create a REST API with DRF

26
29
2

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
26
29