【问题标题】:Cannot import models from another app in Django无法从 Django 中的另一个应用程序导入模型
【发布时间】:2017-10-06 10:16:30
【问题描述】:

所以我在同一个项目中运行了 2 个应用程序。

我的文件结构如下:

/project_codebase
    /project
        __init.py
        settings.py
        urls.py
        wsgi.py
        ...    
    /app1
        ...
    /app2
        ...
    manage.py

因此,出于某种奇怪的原因,我的基本目录有一个不同的名称(即,它以 codebase 结尾)。希望这不是问题。

在我的 settings.py 中,我有这个:

INSTALLED_APPS = [
    ...

    'app1',
    'app2',
]

好的,所以在我的 models.py(来自 app2) 中,我可以使用 from app1.models import * 从 app1 轻松导入模型,但是,当我在我的 模型中使用 from app2.models import * 时。 py(来自 app1),我得到一个 ImportError。

有什么解决办法吗?

【问题讨论】:

  • 可能是循环依赖。 stackoverflow.com/questions/744373/…
  • 好吧,您已经创建了一个循环导入依赖项。为什么需要将每个应用的模型导入另一个?
  • 你应该接受一个答案。

标签: python django django-apps


【解决方案1】:

您需要指定要导入的模型名称,例如 from app1.models import ModelName1, ModelName2。

【讨论】:

    【解决方案2】:

    这可能是由于循环导入问题。为避免这种情况,您应该动态加载模型:

    对于最新版本的 django (1.7+),请使用application registry:

    from django.apps import apps
    MyModel1 = apps.get_model('app1', 'MyModel1')
    

    对于早期的 django 版本 (:

    from django.db.models.loading import get_model
    MyModel1 = get_model('app1', 'MyModel1')
    

    注意 1:如果要定义 外键关系,则不需要单独的导入语句。 Django has you covered 对此:

    如果app1是已安装的应用,则应定义ForeignKey关系如下:

    # in app2.py
    class MyModel2(models.Model):
       mymodel1 = models.ForeignKey('app1.MyModel1')
    

    注意 2:get_model 仅在 app1 是已安装的应用程序且 MyModel1 是您要从 app1 导入的模型时才有效。

    注意3:尽量避免通配符导入(from ... import *),如this is bad practice。

    【讨论】:

    • 为什么 django 切换到那种导入。以前我们习惯将模型导入为“import”
    • @ilyasJumadurdyew 这主要是为了避免在使用“传统”import 语句加载模块时发生的循环导入。使用get_model 或上面显示的外键定义仅在运行时导入模型,一旦加载了所有模块。
    • "Note 1" 将帮助某人在 Django 中交叉链接模型,这是一个非描述性异常:RuntimeError("populate() is not reentrant")!
    【解决方案3】:

    绝对是循环导入。

    但我认为您需要将模型用作某种 RetationFields(ForeignKey、ManyToManyField 或 OneToOneField)参数。所以你需要跳过导入和使用:

    # app1/models.py
    class Model1(models.Model):
        relation_field = models.ForeignKey('app2.Model2')
    

    来自docs:

    如果需要在尚未定义的模型上创建关系,可以使用模型的名称,而不是模型对象本身

    要引用另一个应用程序中定义的模型,您可以显式指定具有完整应用程序标签的模型

    只需将 str 对象作为关系字段的第一个参数,它会导致 <app_name>.<Model_name>。

    注意:最好避免从模块中导入所有内容(from <module_name> import *)

    【讨论】:

      【解决方案4】:

      如果您只想导入某些特定模块,请不要使用import *。

      加载所有库需要更多时间,因此也会影响应用的速度。

      如果您想使用第二个应用程序中的几个模块,那么只需添加模块名称而不是整个库,如下所示:

      from app2.models import Module1, Module2
      

      或者它可能是循环导入问题,如其他澄清。

      谢谢。

      【讨论】:

      • 漂亮 - 这应该是公认的答案
      【解决方案5】:

      我总是使用这个代码,它的工作:)

      from position_app.models import Member

      【讨论】:

        【解决方案6】:

        确保您的应用之一与安装在 Python 环境中的模块之一之间没有名称冲突。如果您使用 pip,您可以运行 pip freeze 来查看已安装模块的列表。

        当我的一个应用程序被命名为“打包”并且安装了打包 python 模块时,我遇到了同样的错误。

        【讨论】:

          【解决方案7】:

          当我尝试从 (django2.2) 中的另一个应用程序导入我的模型时,我也遇到了这个问题

          但最后我导入了它并且它成功地工作了。

          这是我的两个应用程序:

          INSTALLED_APPS = [
              ...
          
              'categories',
              'videos',
          ]
          

          这是我如何将其作为 ForeignKey 连接

          导入到 videos/models.py 文件中的代码
          from django.db import models
          
          class Videos(models.Model):
              categories = models.ForeignKey('categories.Categories', related_name='categories', on_delete=models.CASCADE)
          

          如果想从 categories/models.py 文件中查看我的类别模型,您可以检查此代码,否则忽略它

          from django.db import models
          
          class Categories(models.Model): 
              category_name = models.CharField(max_length=50)
              created_at = models.DateTimeField(auto_now_add=True)
              updated_at = models.DateTimeField(auto_now=True)
          

          【讨论】:

            【解决方案8】:

            循环导入

            在我的情况下,我需要导入的类不是关系字段,而是在方法中使用它。 如果是这种情况,我建议在方法内部导入,否则会引发 AppRegistryNotReady("Models are not loaded.")。

            class Student(CustomUser):
            """ Usuario alumno """
            class Meta:
                verbose_name = "Alumno"
                verbose_name_plural = "Alumnos"
            
            def get_current_school_class(self):
                """ Obtiene el curso actual de un alumno """
                from school.models import SchoolClass, StudentClass
                # proceed with the method...
            

            【讨论】:

              【解决方案9】:

              无需从其他应用导入模型 只需将 app.models 放在外键字段中即可;)

              应用 1:

              class model1(models.Model):
                  field=models.field type ...
              

              应用 2:

              class model2(models.Model):
                  field=models.ForeignKey('app1.model1', on_delete. ...)
              

              为了避免代码更正:D

              【讨论】:

              • 欢迎来到 SO!当你要回答一个已经有公认答案的老问题(这个问题超过 3 岁)时(这里就是这种情况),请问问自己:我真的有实质性的改进吗?如果没有,请考虑不要回答。
              • 完美!感谢这个解决方案效果很好。
              猜你喜欢
              • 2015-10-03
              • 2019-01-24
              • 1970-01-01
              • 2016-11-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多