目前的django文档告诉我:
django.setup()只能调用一次。
因此,请避免将可重用的应用程序逻辑放在独立脚本中,以便您必须从应用程序中的其他位置导入脚本。如果你无法避免,请将调用django.setup()放在if块中:
if __name__ == '__main__':
import django
django.setup()
来源:Calling django.setup() is required for “standalone” Django usage
我在setup.py中使用入口点。这样我就没有__name__ == '__main__'
。
如果使用console_scripts,如何确保只调用一次django.setup()?
我应该在哪里放置django.setup()
?
我遇到的实际错误:Django挂起。原因如下:https://code.djangoproject.com/ticket/27176
我想将我的应用程序移植到当前的django版本。更改为管理命令不是一种选择,因为其他(第三方应用程序)依赖于我的控制台脚本的存在。
答案 0 :(得分:8)
有同样的问题(或类似的东西)。我解决了这个问题:
[警告:肮脏的解决方案]
if not hasattr(django, 'apps'):
django.setup()
这样,即使多次导入它也只会被调用一次
答案 1 :(得分:3)
https://docs.djangoproject.com/en/1.10/_modules/django/#setup我们可以看到django.setup
实际上做了什么。
配置设置(这是访问的一个副作用 第一个设置),配置日志记录并填充应用程序注册表。 如果
set_prefix
为True,则设置thread-local urlresolvers脚本前缀。
因此,基本上为了确保设置已经完成,我们可以检查应用程序是否已准备好并且设置已配置
from django.apps import apps
from django.conf import settings
if not apps.ready and not settings.configured:
django.setup()
答案 2 :(得分:2)
我在两个生产CLI python包中工作,在django.setup()
中显式调用console_scripts
。
您应该注意的最重要的事情是DJANGO_SETTINGS_MODULE
路径中的env
。
您可以在shell脚本中设置此值,甚至可以在python脚本中加载默认设置。
以下是示例:
# setup.py
entry_points={
'my-cli = mypackage.cli:main'
}
# cli.py
import logging
from os import environ as env
if not 'DJANGO_SETTINGS_MODULE' in env:
from mypackage import settings
env.setdefault('DJANGO_SETTINGS_MODULE', settings.__name__)
import django
django.setup()
# this line must be after django.setup() for logging configure
logger = logging.getLogger('mypackage')
def main():
# to get configured settings
from django.conf import settings
# do stuffs
if __name__ == '__main__':
main()
答案 3 :(得分:1)
由于我喜欢无条件代码,因此我使用此解决方案。它与django文档中的相似,但是可以避免使用ul if __name__ == '__pain__'
。
带代码的文件:
# utils/do_good_stuff.py
# This file contains the code
# No `django.setup()` needed
# This code can be used by web apps and console scripts.
from otherlib import othermethod
def say_thank_you():
...
主要文件:
# do_good_stuff_main.py
import django
django.setup()
def say_thank_you_main():
from myapp import do_good_stuff
return do_good_stuff()
setup.py:
'console_scripts': [
'say_thank_you=myapp.do_good_stuff_main:say_thank_you_main',
...
这是我目前的解决方案。 Ffeeback欢迎。有什么需要改进吗?
答案 4 :(得分:0)
(至少在Django 2.2.5中),设置是在导入时配置的。 django.setup()
对其进行配置,因为它会导入它们。两次调用django.setup()
的问题在于,您将两次填充settings.INSTALLED_APPS
中指定的应用程序,这可能会导致各种问题。
if not apps.ready:
检查就是您应该使用的所有方法:
import django
if not apps.ready:
django.setup()
使用if not (apps.ready or settings.configured):
-是错误的,因为设置可能已在其他位置配置了import语句,并且可能仍未填充应用程序,因此在需要时无法调用django.setup()
。
也就是说,如果您知道独立的入口点(例如main.py
),则可以在没有条件的情况下在此处调用它。仅当存在实际运行脚本两次的风险时才需要此条件,也许是通过将独立模块导入另一个独立模块,以便它们都调用django.setup。多次导入一个模块只会运行一次。