5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

django-rest-frameworkのserializerでいろんなメソッドの呼ばれる順番

Last updated at Posted at 2019-03-17

この記事の目的

  • 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_valuevalidate_<field名> が実行されることになりそう
  • to_representation
    • fieldto_representationを呼び出してるくらい?
  • field.to_internal_valueとかfield.to_representationはまた今度読む
5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?