1.问题描述
我在使用django独立进程的时候,简单来说我想在django启动的时候在redy执行一些业务代码,但是运用到了django的模型类,此时模型并未加载,所以报错Apps aren't loaded yet 然后我在网上东拼西凑寻找解决方案,说的是用以下代码即可以解决。因为可以独立加载django模型,但是如果同时在下方导入了其他模块,而其他模块也用了模型,相当于重复导入了,紧接着我又报了错误populate() isn’t reentrant
寻找资料真的痛苦,不过最终找到了,强烈推荐看看独立进程使用django模型及django.setup()使用,看完后就知道错什么地方了,以下即为参考该文章的内容。
import os
import django
# 设置 DJANGO_SETTINGS_MODULE 环境变量(引入settings文件)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project.settings')
# 加载 Django 项目配置
django.setup()
2.独立进程使用django模型 步骤
1.在独立进程的代码文件开头,需要设置 Django 的环境变量,以使其能够正确加载和使用 Django 框架。添加以下代码:
import os
import django
# 设置 DJANGO_SETTINGS_MODULE 环境变量(引入settings文件)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project.settings')
# 加载 Django 项目配置
django.setup()
2.在独立进程中导入需要使用的 Django 模型,可以直接使用 from your_app.models import YourModel 这样的导入语句来引入需要的模型类。
注意:在独立进程中使用 Django 模型需要确保你的 Django 项目已正确配置并且数据库连接可用。同时,你在独立进程中的代码修改不会自动触发 Django 的信号和中间件,因此需要手动处理相关逻辑
3.django.setup()
django.setup() 是 Django 中的一个函数,主要用于设置 Django 的环境和配置。它需要在使用 Django 模型之前调用,以确保 Django 的各项功能能够正常工作。
第一个过程是从INSTALLED_APP中导入每一个内容,这个过程中代码不应该导入任何models,即使是间接的导入。
第二个过程Django尝试导入models中的子模块,并且必须通过models.py和models/init.py。
第三个过程是调用每个application的ready()方法。
os.environ['DJANGO_SETTINGS_MODULE'] = 'project.settings'
django.setup()
DJANGO_SETTINGS_MODULE
环境变量已告知Django使用哪个settings.py
文件。Django会自动根据这个settings.py
文件,加载其中的INSTALLED_APPS
配置,完成必要的应用初始化。
4. RuntimeError: populate() isn’t reentrant
独立进程的入口调用了django.setup()
,但是独立进程在import其他 模块.py文件,其他py文件中又import了其他django模型。但是在这个引入的py中你又不能再调 django.setup()
,因为这个东西只能调一次。
解决思路:通过apps.get_model()
来导入模型,避免重复调用django.setup()
。
apps.get_model() 是 Django 的一个方法,可以在没有调用 django.setup() 的情况下导入模型
from django.apps import apps
Model = apps.get_model('app_label', 'model_name')
- 取第一个参数 app_label 是应用的标签
- 第二个参数 model_name 是模型的名称
- 这个方法会直接从 Django 的注册表中获取模型类,而不会进行任何初始化。
- 使用 apps.get_model() 的好处是:
- 避免重复调用 django.setup()
- 解决循环导入错误
- 在 Django 初始化之前也可以导入模型
总的来说:
通过 apps.get_model() ,可以在无需调用 django.setup() 的情况下,安全地导入 Django 模型。
它通过直接从注册表获取模型类,解决了导入模型前需要初始化的问题。 独立进程使用django模型报错:Apps aren’t loaded yet
问题描述:独立进程使用django模型,导入模型的时候报错:django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
问题原因:出现这个问题的原因可能有如下情况:
- 你根本没有调
django.setup()
- 你调
django.setup()
的位置不对,在加载模型之前了。(应该放在独立进程最前面) - 【隐藏的比较深】你调
django.setup()
时,应用名xxx和和某个文件名xxx.py重名了,而这个xxx.py中又用了django模型,但是这个模型对应的django应用还没执行到。
3个问题的本质都是django.setup() 没有执行完,就使用模型。
我们重点描述一下情况3:
调django.setup()
会循环调传入你settings.py
配置的应用名来调django源码路径\django\apps\config.py 下的create
方法,如下:
@classmethod
def create(cls, entry):
"""
Factory that creates an app config from an entry in INSTALLED_APPS.
"""
# create() eventually returns app_config_class(app_name, app_module).
app_config_class = None
app_name = None
app_module = None
# If import_module succeeds, entry points to the app module.
try:
app_module = import_module(entry)
except Exception:
pass
else:
# If app_module has an apps submodule that defines a single
# AppConfig subclass, use it automatically.
# To prevent this, an AppConfig subclass can declare a class
# variable default = False.
# If the apps module defines more than one AppConfig subclass,
# the default one can declare default = True.
- entry 参数就是你应用名,比如三方的应用名叫:‘django.contrib.auth’,我们自己的应用名xxx。
import_module()存在一个限制就是:
- 如果同时存在一个
.py
文件和一个包(包含__init__.py
)具有相同的名称 - 那么
import_module()
会优先导入.py
文件
问题就出现在这里了,所以我们应用命名时候,注意这种情况- -!