16
11

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 5 years have passed since last update.

脱・とりあえず動く[DRF編]

Posted at

課題

「業務で使っているけど、よく知らない。けどとりあえず動いている」ということが非常に多いので、調べたこと、試したことをまとめていこうと思います。
今回はDjango REST framework編です。

そもそもRESTとは

参考:https://qiita.com/masato44gm/items/dffb8281536ad321fb08
Representation State Transferの略。

特徴としては

  • ステートレス(同じリクエストに対して同じ結果を返す)
  • リクエストメソッドの種類とCRUDが紐づいている(GET→READ、POST→CREATE、PUT→UPDATE、DELETE→DELETE)
  • URLとメソッドの種類で、リソースに対する操作を表現する
    • メソッド:GET URL:/users → ユーザー全取得
    • メソッド:GET URL:/users/1 → ユーザー1を取得 etc...

他にも色々あるけれども、このルールに則っているAPIを「RESTFulなAPI」と呼びます。
一番の特徴は「メソッドとURLでリソースを操作する」ことだと思います。

メリット・デメリット

参考

メリットとしては、

  • URL、APIのルールがわかりやすい
    • 開発側も一貫したルールに基づいて開発しやすい
    • APIを使用する側も使い方がわかりやすい

デメリットとしては

  • 複雑な処理の実装が煩雑
    • どうしてもRESTの考え方に合わない部分も出てくる

あくまでRESTは設計原則なので、原則に合わない部分をどうするか、という点で問題でしょうか。

DRFについて

Django REST Framework(以下DRF)は、Django上でRESTFulなAPIを作成するためのフレームワークです。

ざっくりとした使用法としては、

  • Modelを定義
    • Model:DBに登録するデータクラス。
  • ModelのSerializerを定義
    • Serializer:実際のデータとModelの橋渡しをするクラス。Model ⇆ Serializer ⇆ DBやデータ みたいなイメージ。
  • Viewを定義
    • View:リクエストに対してどのようなレスポンスを返すかを定義したもの。DRFではAPIViewやViewSetというクラスにメソッド別の動作を定義する。
  • URLを設定
    • 指定されたURLとViewを結びつける。

といった流れになります。DRF側で用意されているものを利用すれば、シンプルなAPIなら手軽に作成することができます。

実験

簡単なModelを定義して、CRUD処理を確認します

プロジェクト作成
django-admin startproject sample
アプリ作成
python manage.py startapp drf_sample

設定編集

setting.py
# 追加分のみ
INSTALLED_APP = [
    'drf_sample',
    'rest_framework'
]

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        # テスト用に認証なしで操作できるように設定
        'rest_framework.permissions.AllowAny'
    ]
}

Modelの定義
djangoのデフォルトUserクラスはありますが、今回は実験のため、
first_name,last_name,emailというフィールドを持つUserModelを定義します。

drf_sample.models.py
from django.db import models

class User(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    email = models.EmailField()

Serializerの定義
drf_sample配下にserializers.pyを作成します

drf_sample.serializers.py
from drf_sample.models import User
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

viewの追加

drf_sample.views.py
from rest_framework import viewsets
from drf_sample.models import User
from drf_sample.serializers import UserSerializer

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

URLの追加
drf_sample配下にurls.pyを作成します

drf_sample.urls.py
from rest_framework import routers
from drf_sample.views import UserViewSet

router = routers.DefaultRouter()
router.register(r'users', UserViewSet)

urlpatterns = router.urls

Migrate
python manage.py makemigrations drf_sample
python manage.py migrate

これで完了です。サーバーを起動します。
python manage.py runserver

curlコマンドでCRUD処理を確認します。

GET
curl http://localhost:8000/api/users/
[]
usersで全ユーザーを取得しましたが、まだユーザーがないので空のリストが返ってきました。
では、ユーザーを登録しましょう。
POST
curl -X POST http://localhost:8000/api/users/ -d "first_name=first&last_name=last&email=drf_sample@gmail.com"
{"id":1,"first_name":"first","last_name":"last","email":"drf_sample@gmail.com"}
登録が成功するとそのユーザーのデータが返ってきます。

改めてGETします。
curl http://localhost:8000/api/users/
[{"id":1,"first_name":"first","last_name":"last","email":"drf_sample@gmail.com"}]
先ほど登録したユーザーがリストで返ってきます。
一件取得は
curl http://localhost:8000/api/users/1/
{"id":1,"first_name":"first","last_name":"last","email":"drf_sample@gmail.com"}

これでGET(READ)、POST(CREATE)が確認できました。
PUT
curl -X PUT http://localhost:8000/api/users/1/ -d "first_name=change_first_name&last_name=last&email=drf_sample@gmail.com"
{"id":1,"first_name":"change_first_name","last_name":"last","email":"drf_sample@gmail.com"}

DELETE
curl -X DELETE http://localhost:8000/api/users/1/
確認
curl http://localhost:8000/api/users/
[]

これでCRUD処理は全て確認できました。
参考:http://www.django-rest-framework.org

もっと詳しく

前章のコードをもう少し詳しく見てみます。

Model

ModelクラスはDBのテーブルに対応し、各カラムが各フィールドに対応します。
それぞれの属性にふさわしいフィールドでModelを作成することで、APIを自動生成してくれます。
データのチェックも行ってくれるので、例えばemailフィールドに有効でないメールアドレスを渡すとエラーになったりします。(https://docs.djangoproject.com/ja/2.1/ref/validators/#django.core.validators.EmailValidator)
フィールド一覧:https://docs.djangoproject.com/ja/2.1/ref/models/fields/#model-field-types

Serializer

Serializerの役目は、データとModelの変換です。

  • Modelのフィールドに対するserializerを定義する
  • create(Modelインスタンスの作成),update(Modelインスタンスの更新)等のメソッド,data(ModelをPythonの標準の形にしたもの)等のプロパティが準備されている

などの特徴があります。
必要に応じて各メソッドをオーバーライドしたり、オプションを追加します。
参考:https://www.django-rest-framework.org/api-guide/serializers/

ViewSet

クラスベースのViewです。URLで呼び出されるメソッドを定義します。
(viewは関数でも良いのですが、クラスベースだと再利用しやすいため推奨されているようです)
今回使用したModelViewSetには、デフォルトで以下のメソッドが用意されています。

  • list(全件取得)
  • retrive(一件取得)
  • create(新規作成)
  • update(更新)
  • partial_update(部分更新)
  • destroy(削除)

参考:https://www.django-rest-framework.org/api-guide/viewsets/

Router

ViewSetで定義したメソッドと、リクエストメソッドとURLを対応付けます。
デフォルトだと以下の対応になります。

リクエストメソッド URL 呼び出されるViewSetのメソッド
GET /users/ list
GET /users/{id}/ retrieve
POST /users/ create
PUT /users/{id}/ update
PATCH /users/{id}/ partial_update
DELETE /users/{id}/ destroy

新たなURLを追加したい場合は、ViewSetにメソッドを定義→actionデコレータでリクエストメソッドを指定してやれば、そのメソッド名でURLに追加されます。

参考:https://www.django-rest-framework.org/api-guide/routers/

まとめ

DRFを使用することで、RESTfulなAPIを簡単に開発することができます。
思った以上に便利な機能や設定等があり、うまく利用できればコーディング量を大幅に削減できます。
ただ、より複雑な場合はどのように設計・開発すべきかのベストプラクティスはまだまだ見えていないので、経験を積んで行きたいですね。

全く別件なのですが、先日現場で使えるDjangoの教科書を購入しました。まだ読了はしていないのですが、何と無く使っていた部分が簡潔に説明されており、納得しながら読み進められています。おすすめです。

16
11
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
16
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?