I have
class AnimalSerializer(serializers.ModelSerializer):
class Meta:
model = Animal
fields = "__all__"
Now i run mypy
[mypy]
# The mypy configurations: https://mypy.readthedocs.io/en/latest/config_file.html
python_version = 3.9
check_untyped_defs = True
# disallow_any_explicit = True
disallow_any_generics = True
disallow_untyped_calls = True
disallow_untyped_decorators = True
ignore_errors = False
ignore_missing_imports = True
implicit_reexport = False
strict_optional = True
strict_equality = True
no_implicit_optional = True
warn_unused_ignores = True
warn_redundant_casts = True
warn_unused_configs = True
warn_unreachable = True
warn_no_return = True
mypy_path = /home/simha/app/backend_django/src
plugins =
mypy_django_plugin.main,
mypy_drf_plugin.main
[mypy.plugins.django-stubs]
django_settings_module = petsproject.settings
(venv) $ mypy .
I get
error: Missing type parameters for generic type "ModelSerializer"
The stub file for serializers.ModelSerializer
shows that it inherits from a generic base class BaseSerializer
. This means that ModelSerializer
is also generic:
# (Imports excluded for the sake of brevity)
_MT = TypeVar("_MT", bound=Model) # Model Type
# <-- snip -->
class ModelSerializer(Serializer, BaseSerializer[_MT]):
serializer_field_mapping: Dict[Type[models.Field], Type[Field]] = ...
serializer_related_field: Type[RelatedField] = ...
serializer_related_to_field: Type[RelatedField] = ...
serializer_url_field: Type[RelatedField] = ...
serializer_choice_field: Type[Field] = ...
url_field_name: Optional[str] = ...
instance: Optional[Union[_MT, Sequence[_MT]]] # type: ignore[override]
class Meta:
model: Type[_MT] # type: ignore
fields: Union[Sequence[str], Literal["__all__"]]
read_only_fields: Optional[Sequence[str]]
exclude: Optional[Sequence[str]]
depth: Optional[int]
extra_kwargs: Dict[str, Dict[str, Any]] # type: ignore[override]
def __init__(
self,
instance: Union[None, _MT, Sequence[_MT], QuerySet[_MT], Manager[_MT]] = ...,
data: Any = ...,
partial: bool = ...,
many: bool = ...,
context: Dict[str, Any] = ...,
read_only: bool = ...,
write_only: bool = ...,
required: bool = ...,
default: Union[Union[_MT, Sequence[_MT]], Callable[[], Union[_MT, Sequence[_MT]]]] = ...,
initial: Union[Union[_MT, Sequence[_MT]], Callable[[], Union[_MT, Sequence[_MT]]]] = ...,
source: str = ...,
label: str = ...,
help_text: str = ...,
style: Dict[str, Any] = ...,
error_messages: Dict[str, str] = ...,
validators: Optional[Sequence[Validator[_MT]]] = ...,
allow_null: bool = ...,
allow_empty: bool = ...,
): ...
def update(self, instance: _MT, validated_data: Any) -> _MT: ... # type: ignore[override]
def create(self, validated_data: Any) -> _MT: ... # type: ignore[override]
def save(self, **kwargs: Any) -> _MT: ... # type: ignore[override]
def to_representation(self, instance: _MT) -> Any: ... # type: ignore[override]
def get_field_names(self, declared_fields: Mapping[str, Field], info: FieldInfo) -> List[str]: ...
def get_default_field_names(self, declared_fields: Mapping[str, Field], model_info: FieldInfo) -> List[str]: ...
def build_field(
self, field_name: str, info: FieldInfo, model_class: _MT, nested_depth: int
) -> Tuple[Field, Dict[str, Any]]: ...
def build_standard_field(
self, field_name: str, model_field: Type[models.Field]
) -> Tuple[Field, Dict[str, Any]]: ...
def build_relational_field(
self, field_name: str, relation_info: RelationInfo
) -> Tuple[Type[Field], Dict[str, Any]]: ...
def build_nested_field(
self, field_name: str, relation_info: RelationInfo, nested_depth: int
) -> Tuple[Field, Dict[str, Any]]: ...
def build_property_field(self, field_name: str, model_class: _MT) -> Tuple[Field, Dict[str, Any]]: ...
def build_url_field(self, field_name: str, model_class: _MT) -> Tuple[Field, Dict[str, Any]]: ...
def build_unknown_field(self, field_name: str, model_class: _MT) -> NoReturn: ...
def include_extra_kwargs(
self, kwargs: MutableMapping[str, Any], extra_kwargs: MutableMapping[str, Any]
) -> MutableMapping[str, Any]: ...
def get_extra_kwargs(self) -> Dict[str, Any]: ...
def get_uniqueness_extra_kwargs(
self, field_names: Iterable[str], declared_fields: Mapping[str, Field], extra_kwargs: Dict[str, Any]
) -> Tuple[Dict[str, Any], Dict[str, HiddenField]]: ...
def _get_model_fields(
self, field_names: Iterable[str], declared_fields: Mapping[str, Field], extra_kwargs: MutableMapping[str, Any]
) -> Dict[str, models.Field]: ...
def get_unique_together_validators(self) -> List[UniqueTogetherValidator]: ...
def get_unique_for_date_validators(self) -> List[BaseUniqueForValidator]: ...
When run with the --disallow-any-generics option, MyPy will complain if you inherit from an unparameterised generic, as it is unclear whether you want your inherited class to also be considered generic, or whether you want it to be considered a more concrete version of the base class.
As you have the line model = Animal
in the Meta
class in your derived class, and the stub file annotates ModelSerializer.Meta.model
as being of type Type[_MT]
, my guess is that you do not want want your AnimalSerializer
class to be generic, and instead want it to be specific to an Animal
class that is a subclass of Model
. As such, you need to rewrite your AnimalSerializer
class like this:
class AnimalSerializer(serializers.ModelSerializer[Animal]):
class Meta:
model = Animal
fields = "__all__"