django-stubs:缺少通用类型的类型参数 "ModelSerializer"
django-stubs: Missing type parameters for generic type "ModelSerializer"
我有
class AnimalSerializer(serializers.ModelSerializer):
class Meta:
model = Animal
fields = "__all__"
现在我运行 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 .
我明白了
error: Missing type parameters for generic type "ModelSerializer"
serializers.ModelSerializer
的 stub file 表明它继承自通用基础 class BaseSerializer
。这意味着 ModelSerializer
也是通用的:
# (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]: ...
当 运行 使用 --disallow-any-generics 选项时,如果您从未参数化的泛型继承,MyPy 会抱怨,因为不清楚您是否希望继承的 class 也被被认为是通用的,或者您是否希望它被认为是基础 class.
的更具体版本
因为您在派生 class 的 Meta
class 中有行 model = Animal
,并且存根文件将 ModelSerializer.Meta.model
注释为类型Type[_MT]
,我的猜测是你不希望你的 AnimalSerializer
class 是通用的,而是希望它特定于 Animal
class是 Model
的子 class。因此,您需要像这样重写 AnimalSerializer
class:
class AnimalSerializer(serializers.ModelSerializer[Animal]):
class Meta:
model = Animal
fields = "__all__"
我有
class AnimalSerializer(serializers.ModelSerializer):
class Meta:
model = Animal
fields = "__all__"
现在我运行 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 .
我明白了
error: Missing type parameters for generic type "ModelSerializer"
serializers.ModelSerializer
的 stub file 表明它继承自通用基础 class BaseSerializer
。这意味着 ModelSerializer
也是通用的:
# (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]: ...
当 运行 使用 --disallow-any-generics 选项时,如果您从未参数化的泛型继承,MyPy 会抱怨,因为不清楚您是否希望继承的 class 也被被认为是通用的,或者您是否希望它被认为是基础 class.
的更具体版本因为您在派生 class 的 Meta
class 中有行 model = Animal
,并且存根文件将 ModelSerializer.Meta.model
注释为类型Type[_MT]
,我的猜测是你不希望你的 AnimalSerializer
class 是通用的,而是希望它特定于 Animal
class是 Model
的子 class。因此,您需要像这样重写 AnimalSerializer
class:
class AnimalSerializer(serializers.ModelSerializer[Animal]):
class Meta:
model = Animal
fields = "__all__"