在 Django 4 设置中使用 gettext_lazy 与 django-stubs 时遇到困难,导致导入周期和 mypy 类型推断错误

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

问题:

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 错误的更清洁、更可持续的解决方案的建议。任何见解或替代方法将不胜感激。

可能的解决方案:

考虑过几种解决方案,但都不是理想的:

  1. 禁用 Mypy 键入设置: 禁用 Mypy 设置的类型是一种解决方法,但它可能会损害静态类型的优势。

  2. 从设置中删除

    gettext_lazy
    另一种选择是从设置中删除
    gettext_lazy
    。然而,这与 Django 4 和 5 文档中当前的建议相矛盾,后者仍然主张在
    gettext_lazy
    设置中使用
    LANGUAGE


python django mypy django-settings django-stubs
2个回答
0
投票

处理 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。选择最适合您的项目结构和偏好的一个。


0
投票

也刚刚遇到这个。这在 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")
© www.soinside.com 2019 - 2024. All rights reserved.