如何解决Django抽象类的mypy类型检查错误?
解决Django PreviewMixin的mypy类型检查错误
问题背景
我定义了一个Django抽象混入类PreviewMixin用于生成预览缩略图,代码实际运行无异常,但执行mypy类型检查时出现错误。
混入类代码
from django.core.files.storage import default_storage from django.db import models from sorl.thumbnail import get_thumbnail class PreviewMixin(models.Model): preview = models.ImageField(blank=True, null=True) class Meta: abstract = True def _get_preview_thumbnail(self, geometry_string: str, crop: str = 'noop', quality: int = 100) -> str: preview = '' if self.preview: thumbnail = get_thumbnail(file_=self.preview, geometry_string=geometry_string, crop=crop, quality=quality) preview = default_storage.url(name=thumbnail) return preview
mypy错误信息
error: "DefaultStorage" has no attribute "url" [attr-defined]
使用的包版本
django 4.2.2 mypy 1.4.1 django-stubs 4.2.3 django-stubs-ext 4.2.2 sorl.thumbnail 12.9.0
mypy配置文件(mypy.ini)
[mypy] python_version = 3.11 plugins = mypy_django_plugin.main, mypy_drf_plugin.main exclude = .git, .idea, .mypy_cache, .ruff_cache, node_modules check_untyped_defs = true disallow_untyped_decorators = true disallow_untyped_calls = true ignore_errors = false ignore_missing_imports = true implicit_reexport = false local_partial_types = true no_implicit_optional = true strict_optional = true strict_equality = true warn_unused_ignores = true warn_redundant_casts = true warn_unused_configs = true warn_unreachable = true warn_no_return = true [mypy.plugins.django-stubs] django_settings_module = 'settings'
解决方法
方法1:类型转换(推荐)
django-stubs对DefaultStorage的类型定义未包含url方法,但实际运行时default_storage是具体存储类(如FileSystemStorage)的实例,具备url方法。通过类型转换让mypy识别正确的类型:
修改代码,导入cast和Storage类,然后对default_storage进行类型转换:
from typing import cast from django.core.files.storage import default_storage, Storage # ... 其他导入保持不变 class PreviewMixin(models.Model): # ... 其他代码保持不变 def _get_preview_thumbnail(self, geometry_string: str, crop: str = 'noop', quality: int = 100) -> str: preview = '' if self.preview: thumbnail = get_thumbnail(file_=self.preview, geometry_string=geometry_string, crop=crop, quality=quality) # 类型转换为具备url方法的Storage类型 preview = cast(Storage, default_storage).url(name=thumbnail) return preview
方法2:添加类型忽略注释
如果不想修改类型逻辑,可以直接在报错行添加忽略注释,绕过mypy的检查:
preview = default_storage.url(name=thumbnail) # type: ignore[attr-defined]
方法3:验证存储后端配置
确认项目settings.py中配置的DEFAULT_FILE_STORAGE是具备url方法的存储后端(如默认的django.core.files.storage.FileSystemStorage),确保运行时逻辑的正确性。
内容的提问来源于stack exchange,提问作者Vadim Beglov
相关产品推荐
相关产品推荐

