utamaro’s blog

誰かの役に立つ情報を発信するブログ

DjangoでSerializerを使ったバリデーション方法について

DjangoではRestApiを作成するための便利なライブラリとしてDjango REST frameworkというものがあります。

このライブラリを使うと、簡単にapiを作成することができます。

この記事ではDjango REST frameworkで用意されているserializerを使ったバリデーション方法を紹介します。

また、Django REST frameworkでviewを表示する方法についても紹介します。

views.py

views.pyではviewsetを使って実装しています。

actionを使って、getpostといったメソッドを作らないようにしました。

actionを使った場合はurlsを少し工夫する必要がありますが、それについてはurls.pyを見てください。

from django.http import JsonResponse
from django.shortcuts import render
# Create your views here.
from rest_framework import viewsets
from rest_framework.decorators import action

from apps.xxxxxxx.serializer import SampleSerializer


class SampleViewSet(viewsets.ModelViewSet):
    serializer_class = SampleSerializer

    @action(detail=False, name='sample_post_api')
    def sample_post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        if not serializer.is_valid():
            return JsonResponse({"status": 400}, status=404)
        return JsonResponse(serializer.data, status=200)

    @action(detail=False, name='sample_get_open_view')
    def sample_get(self, request, *args, **kwargs):
        return render(request, 'home.html', status=200)

saple_getではrenderというショートカットを使用してhome.htmlを表示しています。

restframeworkのサンプルでは以下のように実装されているので、以下の方法でも良いです。

    @action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
    def highlight(self, request, *args, **kwargs):
        snippet = self.get_object()
        return Response(snippet.highlighted)

serializer.py

countというフィールドを持っています。

countは-1か1の値を受け付けます。

IntegerFieldではmin_valuemax_valueを使えますが、0は許可してほしくありません。

そういった場合はvalidation_xxxxというようにバリデーションを追加できます。

from rest_framework import serializers

class SampleSerializer(serializers.Serializer):

    count = serializers.IntegerField(min_value=-1, max_value=1)

    def validate_count(self, count):
        if count == 0:
            raise serializers.ValidationError("count is not allowed zero.")
        return count

新しいシリアライザクラスを作成したほうが良いのかもしれません。

urls.py

views.pyで作成したapiを登録します。

restframeworkではrouterというものを使うのが一般的だと思いますが、この記事ではurlpatternsをそのまま使ってます。

routerについてはこちらを参照してください。

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

また、検索するとよく見つかるurl()というのの代わりにpathre_pathを使用しています。

理由はurlが廃止される可能性があるからです。

from django.contrib import admin
from django.urls import path, re_path

from apps.xxxxxxxx.views import SampleViewSet

# admin
urlpatterns = [
    path('admin/', admin.site.urls),
]

# sample api and view
urlpatterns += {
    re_path(r'sample/?$', SampleViewSet.as_view(actions={
        'get': 'sample_get',
    })),
    path('api/sample/post', SampleViewSet.as_view(actions={
        'post': 'sample_post'
    })),
}

.as_viewの’actionを使って登録します。

見るだけでわかると思います。

getでリクエストが来たら、sample_getメソッドへ。

postでリクエストが来たら、sample_postメソッドへ。

ちなみに、以下のように実装しないのには理由があります。

urlpatterns += {
    re_path(r'sample/?$', SampleViewSet.as_view(actions={
        'get': 'sample_get',
        'post': 'sample_post'
    })),
}

このようにすると、/sampleにリクエストした際に、restframeworkが用意している管理画面を表示できません。

postをテストしたいのに、getが最初に表示されるので、管理画面が表示されないのです。