前回は、API Viewクラスについて学びました。
本記事では、シリアライズのバリデーションについて学びます。
前回
シリアライズについて
シリアライズの詳細については、以下の記事を参考にしてください。
バリデーションのエラーメッセージについて
復習になりますが、シリアライズクラスのバリデーションチェックには、「is_valid」関数を用います。
1 2 3 4 |
from news.api.serializers import ArticleSerializer serializer = ArticleSerializer(data={}) serializer.is_valid() False |
上記の場合は、シリアライズの要件を満たさなかったため、Falseになってます。
この場合は、エラーメッセージを取得することができます。
1 2 3 4 5 6 7 8 9 |
serializer.errors { 'author': [ErrorDetail(string='This field is required.', code='required')], 'title': [ErrorDetail(string='This field is required.', code='required')], 'body': [ErrorDetail(string='This field is required.', code='required')], 'location': [ErrorDetail(string='This field is required.', code='required')], 'publication_date': [ErrorDetail(string='This field is required.', code='required')], 'active': [ErrorDetail(string='This field is required.', code='required')] } |
Djangoの開発経験があれば想像できると思いますが、これはDjangoのForm機能と同じです。
尚、is_validを実行しないとエラーメッセージを取得することができません。
1 2 3 4 5 6 7 8 9 10 |
serializer = ArticleSerializer(data={}) >>> serializer.errors Traceback (most recent call last): File "<console>", line 1, in <module> File "/Users/hoge/Desktop/django-rest-framework-cookbook/venv/lib/python3.7/site-packages/rest_framework/serializers.py", line 567, in errors ret = super().errors File "/Users/hoge/Desktop/django-rest-framework-cookbook/venv/lib/python3.7/site-packages/rest_framework/serializers.py", line 271, in errors raise AssertionError(msg) AssertionError: You must call `.is_valid()` before accessing `.errors`. |
バリデーションの種類
公式サイトによると、バリデーションを実装する方法は、3つほどあります。
1. 変数にバリデーションをつける(UniqueValidator)
UniqueValidatorは、シリアライズクラスの変数にバリデーションをつける方法です。
1 2 3 4 5 6 |
from rest_framework.validators import UniqueValidator slug = SlugField( max_length=100, validators=[UniqueValidator(queryset=BlogPost.objects.all())] ) |
2. シリアライズクラスのMeta情報としてバリデーションをつける(UniqueTogetherValidator)
UniqueTogetherValidatorは、シリアライズクラスのMeta情報にバリデーションを付与します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from rest_framework.validators import UniqueTogetherValidator class ExampleSerializer(serializers.Serializer): # ... class Meta: # ToDo items belong to a parent list, and have an ordering defined # by the 'position' field. No two items in a given list may share # the same position. validators = [ UniqueTogetherValidator( queryset=ToDoItem.objects.all(), fields=['list', 'position'] ) ] |
3. バリデーション関数を実装する
3つ目は、バリデーション関数をシリアライズクラスに定義することです。こちらを今回試してみようと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# news/api/serializers.py from rest_framework import serializers from news.models import Article class ArticleSerializer(serializers.Serializer): """Article Serializer """ id = serializers.IntegerField(read_only=True) author = serializers.CharField() title = serializers.CharField() description = serializers.CharField() # new body = serializers.CharField() location = serializers.CharField() publication_date = serializers.DateField() active = serializers.BooleanField() created_at = serializers.DateTimeField(read_only=True) updated_at = serializers.DateTimeField(read_only=True) def create(self, validate_data): ... def update(self, instance, validated_data): ... def validate(self, data): """Check that description and title are different""" if data["title"] == data["description"]: raise serializers.ValidationError( "Title and Description must be different from one another") return data |
validate関数をオーバーライドしました。
titleとdescriptionの内容が同じの場合は、ValidationErrorが発生します。
動作確認をしてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
python manage.py shell import datetime from news.api.serializers import ArticleSerializer serializer = ArticleSerializer(data={"author": "admin", "title": "some", "description": "some", "location": "kanagawa", "publication_date": format(datetime.date.today(), '%Y-%m-%d'), "active": True, "body": "test"}) serializer.is_valid() serializer.errors {'non_field_errors': [ErrorDetail( string='Title and Description must be different from one another', code='invalid')]} |
エラーが発生しましたね。
ブラウザ上でも試して見ましょう。
以下のコマンドで、Djangoの開発用サーバーを起動してください。
1 |
python manage.py runserver |
次に「http://localhost:8000/api/articles/」にアクセスしてください。
続いて、画面下部にあるContentにJSONデータを入力します。

1 2 3 4 5 6 7 8 9 |
{ "author": "selfnote", "title": "TEST", "description": "TEST", "body": "this is a first post", "location": "tokyo", "publication_date": "2020-05-22", "active": true } |
この時、titleとdescriptionの文字列を一致させてください。
この状態で、「POST」ボタンを押下します。

OKですね。
補足ですが、views.pyに以下の関数が実装されてます。
1 2 3 4 5 6 7 8 9 |
class ArticleListCreateAPIView(APIView): ... def post(self, request): serializer = ArticleSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) |
is_validがFalseの場合は、
が返されるので、エラー画面が表示できるというわけです。return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST
個別バリデーション
個別にバリデーションを実装することもできます。
1 2 3 4 5 |
def validate_title(self, value): if len(value) < 60: raise serializers.ValidationError("The title has to be at least 60 charactor") return value |
validate_XXXX(変数名)の命名規則があります。
このバリデーションでは、titleに60文字未満の文字列が渡された場合、ValidationErrorが発生するようにしました。
動作確認をしてみましょう。
テスト用のJSONデータは、以下のようになってます。
1 2 3 4 5 6 7 8 9 |
{ "author": "selfnote", "title": "first post", "description": "post", "body": "this is a first post", "location": "tokyo", "publication_date": "2020-05-22", "active": true } |

POSTを押下します。

OKですね。
次回
次回は、ModelSerializerクラスについて学びます。
関連記事
こちらもどうぞ
Djangoおすすめ書籍
Djangoを学ぶなら以下の書籍がオススメです。
緑 -> 赤 -> 紫の順でやればOKです。読みやすい英語で書かれているので、英語力もついでに上がるかもしれません^^
コメントを残す
コメントを投稿するにはログインしてください。