この記事の目的
- django-rest-framework を使っていて、serializerが中でどういう処理をしているのかがわからなくてつらい
- そうだ、フレームワークの中身を読んでみよう
環境
- djangorestframework: 3.9.1
見るところ
- rest_framework/serializers.py
-
class Serializer(BaseSerializer)
の辺り - とりあえずここ理解すれば他もなんとかなる?
-
読む
- renderersとかmixinsとかは後回しでいきなりserializers
to_internal_value(self, data)
471 def to_internal_value(self, data):
472 """
473 Dict of native values <- Dict of primitive datatypes.
474 """
475 if not isinstance(data, Mapping):
476 message = self.error_messages['invalid'].format(
477 datatype=type(data).__name__
478 )
479 raise ValidationError({
480 api_settings.NON_FIELD_ERRORS_KEY: [message]
481 }, code='invalid')
- 受け取ったデータ型の検証とか?
483 ret = OrderedDict()
484 errors = OrderedDict()
485 fields = self._writable_fields
-
ret
: 最終的な返却値 -
errors
: 例外情報 -
fields
:to_internal_value
で処理する対象が格納されている。-
_writable_fields
は以下の通り。
-
367 @cached_property
368 def _writable_fields(self):
369 return [
370 field for field in self.fields.values() if not field.read_only
371 ]
-
read_only
プロパティがFalse
になっているfieldだけが含まれるらしい。
487 for field in fields:
488 validate_method = getattr(self, 'validate_' + field.field_name, None)
489 primitive_value = field.get_value(data)
490 try:
491 validated_value = field.run_validation(primitive_value)
- fieldの
run_vaildation
を実行
523 def run_validation(self, data=empty):
524 """
525 Validate a simple representation and return the internal value.
526
527 The provided data may be `empty` if no representation was included
528 in the input.
529
530 May raise `SkipField` if the field should not be included in the
531 validated data.
532 """
533 (is_empty_value, data) = self.validate_empty_values(data)
534 if is_empty_value:
535 return data
536 value = self.to_internal_value(data)
537 self.run_validators(value)
538 return value
- 渡ってきた値の
to_internal_value
を呼び出し。- ここの処理はまた今度読む
492 if validate_method is not None:
493 validated_value = validate_method(validated_value)
-
validate_<field名>
という名前でメソッドが宣言されてたらそれを実行する
494 except ValidationError as exc:
495 errors[field.field_name] = exc.detail
496 except DjangoValidationError as exc:
497 errors[field.field_name] = get_error_detail(exc)
498 except SkipField:
499 pass
- 例外が発生したらerrorsに入れる
500 else:
501 set_value(ret, field.source_attrs, validated_value)
- validate_のメソッドを実行した結果を
ret
に入れる
503 if errors:
504 raise ValidationError(errors)
- 何かしらのエラーがあったら例外発火
506 return ret
to_representation
508 def to_representation(self, instance):
509 """
510 Object instance -> Dict of primitive datatypes.
511 """
512 ret = OrderedDict()
513 fields = self._readable_fields
-
fields
:_readable_fields
で取得-
_readable_fields
は以下の処理 -
write_only
でないフィールドを取得している
-
373 @cached_property
374 def _readable_fields(self):
375 return [
376 field for field in self.fields.values()
377 if not field.write_only
378 ]
514
515 for field in fields:
516 try:
517 attribute = field.get_attribute(instance)
518 except SkipField:
519 continue
-
instance
から指定のフィールドに格納されているデータを取得
521 # We skip `to_representation` for `None` values so that fields do
522 # not have to explicitly deal with that case.
523 #
524 # For related fields with `use_pk_only_optimization` we need to
525 # resolve the pk value.
526 check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
527 if check_for_none is None:
528 ret[field.field_name] = None
529 else:
530 ret[field.field_name] = field.to_representation(attribute)
- コメントのとおり…
-
to_internal_value
と同様に、fieldのto_representation
も順に呼び出される
531
532 return ret
まとめ
- to_internal_value
- 各fieldに対して
to_internal_value
とvalidationを繰り返してる - オブジェクトがネストされているときは、深いところから
to_internal_value
とvalidate_<field名>
が実行されることになりそう
- 各fieldに対して
- to_representation
- 各
field
のto_representation
を呼び出してるくらい?
- 各
-
field.to_internal_value
とかfield.to_representation
はまた今度読む