【问题标题】:Avoiding circular imports in Django Models (Config class)避免在 Django 模型中循环导入(配置类)
【发布时间】:2018-12-25 07:16:15
【问题描述】:

我在 django 中创建了一个配置模型,以便站点管理员可以即时更改一些设置,但是有些模型依赖于这些配置。我正在使用 Django 2.0.2 和 Python 3.6.4。

我在 models.py 所在的目录下创建了一个 config.py 文件。

让我paracode(paraphase代码?Real Enum有更多选择):

# models.py
from .config import *

class Configuration(models.Model):
    starting_money = models.IntegerField(default=1000)

class Person(models.Model):
    funds = models.IntegarField(default=getConfig(ConfigData.STARTING_MONEY))

# config.py
from .models import Configuration

class ConfigData(Enum):
    STARTING_MONEY = 1
def getConfig(data):
    if not isinstance(data, ConfigData):
        raise TypeError(f"{data} is not a valid configuration type")
    try:
        config = Configuration.objects.get_or_create()
    except Configuration.MultipleObjectsReturned:
        # Cleans database in case multiple configurations exist.
        Configuration.objects.exclude(Configuration.objects.first()).delete()
        return getConfig(data)
    if data is ConfigData.MAXIMUM_STAKE:
        return config.max_stake

如何在没有导入错误的情况下执行此操作?我试过绝对进口

【问题讨论】:

  • 绝对导入不会有任何好处,因为循环导入仍然存在。您尝试导入需要当前文件才能加载的文件。

标签: django python-3.x django-models python-import


【解决方案1】:

Willem Van Onsem 的解决方案是一个很好的解决方案。我有一种不同的方法,我使用django's Applications registry 用于循环模型依赖项。我将其作为替代解决方案发布在这里,部分原因是我希望获得更有经验的 Python 编码人员的反馈,以了解这种方法是否存在问题。

在实用程序模块中,定义以下方法:

from django.apps import apps as django_apps

def model_by_name(app_name, model_name):
  return django_apps.get_app_config(app_name).get_model(model_name)

然后在你的getConfig中,省略导入并替换行

config = Configuration.objects.get_or_create()

以下内容:

config_class = model_by_name(APP_NAME, 'Configuration')
config = config_class.objects.get_or_create()

【讨论】:

    【解决方案2】:

    您可以推迟加载models.py,方法是在getConfig(data) 函数中加载它,因此我们在加载时不再需要models.py config.py:

    # config.py (no import in the head)
    class ConfigData(Enum):
        STARTING_MONEY = 1
    
    def getConfig(data):
        from .models import Configuration
        if not isinstance(data, ConfigData):
            raise TypeError(f"{data} is not a valid configuration type")
        try:
            config = Configuration.objects.get_or_create()
        except Configuration.MultipleObjectsReturned:
            # Cleans database in case multiple configurations exist.
            Configuration.objects.exclude(Configuration.objects.first()).delete()
            return getConfig(data)
        if data is ConfigData.MAXIMUM_STAKE:
            return config.max_stake

    因此我们config.py 中加载models.py。我们仅在实际执行 getConfig 函数时检查它是否已加载(如果未加载则加载),该函数在该过程的后期。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-06
      • 2020-07-11
      • 1970-01-01
      相关资源
      最近更新 更多