django-stubs:缺少泛型类型“ModelSerializer”的类型参数

问题描述 投票:0回答:1

我有

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"

python python-typing mypy django-stubs
1个回答
3
投票

serializers.ModelSerializer

存根文件
显示它继承自通用基类
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 会抱怨,因为不清楚您是否希望继承的类也被视为泛型,或者是否希望它被视为泛型基类的更具体版本。

由于派生类中的

model = Animal
类中有
Meta
行,并且存根文件将
ModelSerializer.Meta.model
注释为
Type[_MT]
类型,我的猜测是您不希望使用
AnimalSerializer
类是通用的,而是希望它特定于作为
Animal
子类的
Model
类。因此,您需要像这样重写您的
AnimalSerializer
类:

class AnimalSerializer(serializers.ModelSerializer[Animal]):
    class Meta:
        model = Animal
        fields = "__all__"
© www.soinside.com 2019 - 2024. All rights reserved.