-
-
Couldn't load subscription status.
- Fork 131
Description
TL;DR: Serializer behavior with many=True is funky. djangorestframework-stubs 3.16.3 changed the behavior of ModelSerializer.instance attribute. If this caused a regression in your use case, please comment below.
Problem
>>> from rest_framework.serializers import *
>>> class MySer(Serializer):
... a = CharField(10)
...
>>> type(MySer())
<class '__main__.MySer'>
>>> type(MySer(many=True))
<class 'rest_framework.serializers.ListSerializer'>Django REST Framework contains a particular trick: when creating an instance of any class that derives from Serializer with the parameter many=True, then the constructor does not actually return an instance of the class itself, but wraps the instance with ListSerializer. This is done using Python's magic __new__() method:
Currently, this cannot be accurately described for the mypy type checker, because the return types from __new__() are constrained: they can only be subclasses of the "self" type:
ModelSerializer many=True work-around was removed
Up until version 3.16.2, djangorestframework-stubs contained a hack in the ModelSerializer class. The instance field was typed as Model | Sequence[Model], to acommodate for the fact that ModelSerializer could be instanciated with either many=True or many=False.
This hack was removed in version 3.16.3 -- PR #719:
- There were multiple questions about this behavior and multiple requests to remove it.
- With the "union" approach,
instancefield type is compatible with neitherModelnorlist[Model], requiring an override in both cases. - I expect that in accessing
instanceof models withmany=Trueis not a common use case -- it's a helpful convenience mostly for nested serializers.
3.16.3, please share it in a comment below.