DRF一覧

Django REST framework で API のバリデーションを実装する

Django REST framework (DRF)で API のバリデーションを実装します。

Django のバリデーションはフォームの役割ですが、DRF のバリデーションはシリアライザの役割です。記述方法は違いますが、実装方法は似ているので、Django のバリデーションに慣れている人は、DRF のバリデーション実装方法もすぐに慣れると思います。

実装イメージ

環境とバージョン

  • CentOS 7.4
  • Python 3.6.4
  • Django 2.0.3
  • Django REST framework 3.8.2

インストール

Python

$ sudo yum install -y https://centos7.iuscommunity.org/ius-release.rpm
$ sudo yum install -y python36u python36u-libs python36u-devel python36u-pip

Python は IUS リポジトリの Python 3.6 をインストールします。CentOS 7 で Python3 を使う方法として、SCL もありますが、コマンドやパスが複雑になるので、私は、IUS リポジトリの Python を使います。

Django

$ sudo pip install django

Django をインストールします。

Django REST framework

$ sudo pip install djangorestframework

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

実装

startproject, startapp

$ django-admin startproject drf_validation
$ cd drf_validation/
$ python3.6 manage.py startapp app

Django のコマンドを使って、プロジェクトの雛形を生成します。

settings.py

...
ALLOWED_HOSTS = ['*']
INSTALLED_APPS = [
    ...
    'rest_framework',
    'app.apps.AppConfig',
]
...

雛形で生成した settings.py を修正していきます。

外部からのアクセスを許可するために、ALLOWED_HOSTS に ‘*’ をセットし、INSTALLED_APPS に先ほど、生成したアプリケーション app と、Django REST framework の rest_framework を追加します。

serializers.py

from django.contrib.auth.models import User
from rest_framework import serializers

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

    def validate_username(self, username):
        if 'hoge' in username.lower():
            raise serializers.ValidationError('The username `hoge` can not be used.')
        return username

    def validate(self, data):
        if 'hoge' in data['first_name'].lower() and 'fuga' in data['last_name'].lower():
            raise serializers.ValidationError('The first name `hoge` and last name `fuga` can not be used.')
        return data

シリアライザ serializers.py を作成し、バリデーションを実装します。通常の Django だとフォームでやるやつですね。

上記の例では、Django の認証用モデル User に対しバリデーション処理を実装しています。

  • ユーザ名 hoge の場合はエラー
  • ファーストネームが hoge かつ、ラストネームが fuga の場合はエラー

フィールド単位のバリデーションは、validation_フィールド名関数で、フィールドの組み合わせでバリデーションしたい場合は、validation 関数で実装します。通常の Django のフォームの clean と一緒ですね。

ここで ValidationError で raise すると、レスポンスが HTTP 400 Bad Request になります。

views.py

from django.contrib.auth.models import User
from rest_framework import viewsets
from app.serializers import UserSerializer

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer

views.py です。DRF デフォルトの動作を変えたい場合は、ここで、該当する関数をオーバーライドすることで実現することができます。

urls.py

from django.urls import path, include
from rest_framework import routers

from app import views

router = routers.DefaultRouter()
router.register('user', views.UserViewSet)

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

urls.py で URL と view をマッピングします。

tree

$ tree
.
├── app
│   ├── __init__.py
│   ├── apps.py
│   ├── serializers.py
│   └── views.py
├── drf_validation
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

2 directories, 9 files

ファイル構成はこのようになりました。

動作確認

DB migrate

$ python3.6 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying sessions.0001_initial... OK

Django 認証用のモデルを使用しますので、DB migrate をします。

runserver

$ python3.6 manage.py runserver 0.0.0.0:8000

動作確認のため、Django デバッグサーバの runserver を起動します。

POST /api/user/

http://IPアドレス:8000/api/user/ にアクセスすると、入力フォームのページが出てきますので、そこでバリデーションの動作を確認することができます。

まとめ

Django REST framework で API のバリデーションを実装しました。

通常の Django のバリデーションと同じように実装できるので、簡単に実装することができましたね。