django-rest-frameworkを学び始めました。関連の記事を書いていきます。
ちょっと裏で動いていることが多くてなかなか理解しづらいですが、簡単なところから記事にいていこうと思います。
djangoのプロジェクト作成とか、django-rest-frameworkとはってところとか、シリアライザってなに?ってところは端折ります(別で記事にするかもしれません)。
ではいきます。
ModelSerializerのvalidationについて
ModelSerializerを継承したselializerの中で以下のように書くと、項目名に対して独自のバリデーションを定義することができます。
class XXXXSerializer(serializers.ModelSerializer):
class Meta:
model = XXXX
fields = "__all__"
def validate_項目名(self, value):
if 条件:
raise serializers.ValidationError(
エラー時の挙動
)
return value
これに対して、viewから以下のようにして呼びます。
serializer = XXXXSerializer(data=data)
serializer.is_valid()
is_valid()
で なにが呼ばれているかという話ですね。
順番に追っていきましょう。
まず、BaseSerializer
のis_valid()
メソッドに行き着きます。
その中のself.run_validation(self.initial_data)
が呼ばれます。ここで、serializerはModelSerializerを継承しているので、BaseSerializerのサブクラスのSerializerやModelSerializerでrun_validation
があればそちらが呼ばれますね。
今回はSerializerにだけあったので、Serializerのrun_validation
が呼ばれます。
その中のself.to_internal_value(data)
が呼ばれ、見たかったものがありました。
def to_internal_value(self, data):
"""
Dict of native values <- Dict of primitive datatypes.
"""
if not isinstance(data, Mapping):
message = self.error_messages['invalid'].format(
datatype=type(data).__name__
)
raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: [message]
}, code='invalid')
ret = OrderedDict()
errors = OrderedDict()
fields = self._writable_fields
for field in fields:
# ここ!!!
validate_method = getattr(self, 'validate_' + field.field_name, None)
primitive_value = field.get_value(data)
try:
validated_value = field.run_validation(primitive_value)
if validate_method is not None:
validated_value = validate_method(validated_value)
except ValidationError as exc:
errors[field.field_name] = exc.detail
except DjangoValidationError as exc:
errors[field.field_name] = get_error_detail(exc)
except SkipField:
pass
else:
set_value(ret, field.source_attrs, validated_value)
if errors:
raise ValidationError(errors)
return ret
#ここ!!
ってかいてあるところですね。
多分ですが項目ごとの標準のvalidateが呼ばれたあとに独自のvalidateが呼ばれる感じなんですかね。
validate_method
という変数に、フィールドごとのvalidateメソッドを集めて、
validated_value = validate_method(validated_value)
で実行してますね。
pythonだとメソッド書くときにこんな書き方が出来るんですかね?
getattr
関数で出来るみたいですね。便利。。
これは使い方覚えておきたいとことですね。
以下のように書くとメソッドを文字列から呼べるみたいです。
class test:
def a(self):
return 5
def b(self,i):
print("b" + str(i))
def c(self,i,j):
print("b"+str(i)+str(j))
testclass = test()
print(getattr(testclass,"a")())
d = getattr(testclass, "b")(6)
e = getattr(testclass, "c")(7,8)
基本的なことだと思いますが、とりあえず一つ知れて良かったです。
getattrなどについてはまた詳しくやりたいですね。
では今回はここまでです!