问题:
Mypy 错误: mypy遇到的错误如下:
error:Import cycle from Django settings module prevents type inference for 'LANGUAGES' [misc]
在使用 django-stubs 时,我在 Django 4 设置中使用
gettext_lazy
时遇到了挑战。 Django 4 中的最新更新对 gettext_lazy
的类型进行了更改,其中旧的返回类型为 str
,新类型为 _StrPromise
。该问题是由于 _StrPromise
是在“django-stubs/utils/function.pyi”中定义的,并且在此文件中,还导入了 django.db.model
来导入设置。这将创建循环导入。
当前模块版本:
打字 mypy =“1.7” django-stubs =“4.2.7”
Django 依赖项 姜戈 =“4.2.10”
在 Django 4 设置的上下文中,使用更新的
gettext_lazy
类型,寻求关于循环导入问题和 mypy 错误的更清洁、更可持续的解决方案的建议。任何见解或替代方法将不胜感激。
可能的解决方案:
考虑过几种解决方案,但都不是理想的:
禁用 Mypy 键入设置: 禁用 Mypy 设置的类型是一种解决方法,但它可能会损害静态类型的优势。
从设置中删除
gettext_lazy
:
另一种选择是从设置中删除 gettext_lazy
。然而,这与 Django 4 和 5 文档中当前的建议相矛盾,后者仍然主张在 gettext_lazy
设置中使用 LANGUAGE
。
处理 Django 设置中的循环导入和 Mypy 键入问题,尤其是 Django 4 中更新的 gettext_lazy 键入问题,确实具有挑战性。让我们探索一些解决此问题的替代方法:
单独的配置模块: 不要直接在 settings.py 文件中定义设置,而是创建一个单独的模块(例如 settings_config.py),在其中定义设置。此模块不应从 Django 模型或其他可能导致循环导入的模块导入任何内容。然后,在 settings.py 中,从 settings_config.py 导入设置。这种分离有助于打破循环依赖。
示例:
# settings_config.py
from django.utils.translation import gettext_lazy as _
LANGUAGE_CODE = 'en-us'
LANGUAGES = [
('en', _('English')),
('fr', _('French')),
]
# settings.py
from .settings_config import *
使用字符串代替常量: 不要在设置中直接引用 gettext_lazy,而是使用将在运行时解析的字符串。虽然这可能无法提供静态类型的好处,但它可以帮助避免循环导入。 示例:
# settings.py
LANGUAGES = [
('en', 'English'),
('fr', 'French'),
]
自定义打字存根: 如果现有存根导致循环导入,您可以为 gettext_lazy 或 _StrPromise 创建自定义类型存根。这种方法涉及在单独的文件中定义必要的类型,而不导入有问题的模块。 示例:
# custom_gettext_lazy.pyi
from typing import Any
class _StrPromise:
def __init__(self, message: str):
pass
def __str__(self) -> str:
...
def gettext_lazy(message: str) -> _StrPromise: ...
然后您可以在设置中使用 gettext_lazy 并进行正确的输入,希望它可以避免循环导入问题。
这些方法应该有助于缓解循环导入问题,同时仍然允许您在 Django 设置中使用 gettext_lazy。选择最适合您的项目结构和偏好的一个。
也刚刚遇到这个。这在 django-stubs 自述文件中进行了解释。
如果您在自己的代码中遇到此错误,您可以将 Promise 强制转换为 str (导致翻译被评估),或者在类型提示中使用 django-stubs-ext 中的 StrPromise 或 StrOrPromise 类型。
要获取类型提示,您需要安装存根扩展:
pip install django-stubs-ext
然后您可以导入提示:
from django_stubs_ext import StrPromise
my_lazy_str: StrPromise = gettext_lazy("foobar")