■
DjangoでSerializerを使ったバリデーション方法について
DjangoではRestApiを作成するための便利なライブラリとしてDjango REST framework
というものがあります。
このライブラリを使うと、簡単にapiを作成することができます。
この記事ではDjango REST framework
で用意されているserializer
を使ったバリデーション方法を紹介します。
また、Django REST framework
でviewを表示する方法についても紹介します。
views.py
views.py
ではviewsetを使って実装しています。
action
を使って、get
やpost
といったメソッドを作らないようにしました。
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_value
とmax_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()
というのの代わりにpath
とre_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が最初に表示されるので、管理画面が表示されないのです。