« ^ »
[WIP]

Django REST Framework 3.14から3.15のモデルシリアライザの挙動について考えてみる

所要時間: 約 2分

2つの環境で検証

python3.10 -m venv drf314 venvs/ 
venvs/drf314/bin/pip install django==3.2.25 djangorestframework==3.14.0
python3.10 -m venv venvs/drf315 
venvs/drf315/bin/pip install django==3.2.25 djangorestframework==3.15.1

影響のある修正

https://github.com/encode/django-rest-framework/pull/9030

関係のある定義

モデル

  • blank
  • null
  • default

シリアライザーフィールド

  • required
  • allow_null
  • default

マトリックス

フィーmodelmodelmodelserializerserializerserializer期待する動作
ルドblanknulldefaultrequiredallow_nulldefault
aaなしなしなしなしなしなし
bbFalseなしなしFalseなしなし
ccTrueなしなしTrueなしなし
ddなしFalseなしなしFalseなし
eeFalseFalseなしFalseFalseなし
ffTrueFalseなしTrueFalseなし
ggなしTrueなしなしTrueなし
hhFalseTrueなしFalseTrueなし
iiTrueTrueなしTrueTrueなし
jjなしなし1なしなし1
kkFalseなし1Falseなし1
llTrueなし1Trueなし1
mmなしFalse1なしFalse1
nnFalseFalse1FalseFalse1
ooTrueFalse1TrueFalse1
ppなしTrue1なしTrue1
qqFalseTrue1FalseTrue1
rrTrueTrue1TrueTrue1

プロジェクトの準備

venvs/drf314/bin/django-admin startproject proj .
venvs/drf314/bin/python manage.py startapp app
venvs/drf314/bin/python manage.py migrate
venvs/drf314/bin/python manage.py makemigrations
venvs/drf314/bin/python manage.py shell
from app.serializers import ExampleSerializer
ka = ExampleSerializer(data={"a": 1, "b": 1, "c": 1, "d": 1, "e": 1, "f": 1, "g": 1, "h": 1})

ka.is_valid(raise_exception=True)
kb = ka.save()

kc = ExampleSerializer(instance=kb, data={"a":2, "g": 2})
kc.is_valid(raise_exception=True)
kd = kc.save()
>>> from app.serializers import ExampleSerializer
>>> ka = ExampleSerializer(data={"a": 1, "b": 1, "c": 1, "d": 1, "e": 1, "f": 1, "g": 1, "h": 1})
>>> ka.is_valid(raise_exception=True)
True
>>> kb = ka.save()
>>> kc = ExampleSerializer(instance=kb, data={"a":2, "g": 2})
>>> kc.is_valid(raise_exception=True)
True
>>> kc.to_internal_value()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: Serializer.to_internal_value() missing 1 required positional argument: 'data'
>>> kc.to_internal_value(data={"a":2, "g": 2})
OrderedDict([('a', 2), ('g', 2)])
>>> from app.serializers import ExampleSerializer
>>> ka = ExampleSerializer(data={"a": 1, "b": 1, "c": 1, "d": 1, "e": 1, "f": 1, "g": 1, "h": 1})
>>> ka.is_valid(raise_exception=True)
True
>>> kb = ka.save()
>>> kb

a = 1
b = 1
c = 1
d = 1
e = 1
f = 1
g = 1
h = 1
        
>>> kc = ExampleSerializer(instance=kb, data={"a":2, "g": 2})
>>> kc.is_valid(raise_exception=True)
True
>>> kd = kc.save()
>>> kd

a = 2
b = 1
c = 1
d = 1
e = 1
f = 1
g = 2
h = 1
        
>>>
venvs/drf315/bin/python manage.py shell
from app.serializers import ExampleSerializer
ka = ExampleSerializer(data={"a": 1, "b": 1, "c": 1, "d": 1, "e": 1, "f": 1, "g": 1, "h": 1})

ka.is_valid(raise_exception=True)
kb = ka.save()

kc = ExampleSerializer(instance=kb, data={"a":2, "g": 2})
kc.is_valid(raise_exception=True)
kd = kc.save()
>>> from app.serializers import ExampleSerializer
>>> ka = ExampleSerializer(data={"a": 1, "b": 1, "c": 1, "d": 1, "e": 1, "f": 1, "g": 1, "h": 1})
>>> ka.is_valid(raise_exception=True)
True
>>> kb = ka.save()
>>> kb

a = 1
b = 1
c = 1
d = 1
e = 1
f = 1
g = 1
h = 1
        
>>> kc = ExampleSerializer(instance=kb, data={"a":2, "g": 2})
>>> kc.is_valid(raise_exception=True)
True
>>> kd = kc.save()
>>> kd

a = 2
b = 1
c = 1
d = 1
e = 1
f = 1
g = 2
h = 1
        
>>>

所感

正しい挙動のように思える。何がなんだか分からない。