【问题标题】:django-stubs: Missing type parameters for generic type "ModelSerializer"django-stubs:缺少泛型类型“ModelSerializer”的类型参数
【发布时间】:2021-10-18 04:05:34
【问题描述】:

我有

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 type-hinting mypy python-typing django-stubs


    【解决方案1】:

    serializers.ModelSerializerstub file 表明它继承自通用基类 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 会报错,因为不清楚您是否希望您继承的类也被视为泛型,或者您是否希望它是被认为是基类的更具体版本。

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

    class AnimalSerializer(serializers.ModelSerializer[Animal]):
        class Meta:
            model = Animal
            fields = "__all__"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 2016-06-13
      • 2023-02-01
      • 1970-01-01
      • 2011-12-29
      • 2017-10-30
      • 2020-08-04
      相关资源
      最近更新 更多