簡體   English   中英

如何在 console_script 中調用 django.setup()?

[英]How to call django.setup() in console_script?

當前的 Django 文檔告訴我:

django.setup() 只能被調用一次。

因此,避免將可重用的應用程序邏輯放在獨立腳本中,以便您必須從應用程序的其他地方的腳本導入。 如果無法避免,請將調用 django.setup() 放在 if 塊中:

if __name__ == '__main__':
    import django
    django.setup()

來源: “獨立”Django 使用需要調用 django.setup()

我在 setup.py 中使用入口點。 這樣我就沒有__name__ == '__main__'

問題

如果使用console_scripts ,如何確保 django.setup() 只被調用一次?

我應該把django.setup()放在哪里?

背景

我遇到的實際錯誤:Django 掛起。 原因如下: https : //code.djangoproject.com/ticket/27176

我想將我的應用程序移植到當前的 django 版本。 更改為管理命令不是一種選擇,因為其他(第三方應用程序)依賴於我的控制台腳本的存在。

有同樣的問題(或類似的問題)。 我通過執行以下操作解決了它:

[警告:骯臟的解決方案]

if not hasattr(django, 'apps'):
    django.setup()

這樣即使多次導入它也只會被調用一次

在這里https://docs.djangoproject.com/en/1.10/_modules/django/#setup我們可以看到django.setup實際做了什么。

配置設置(這是訪問第一個設置的副作用),配置日志記錄並填充應用程序注冊表。 如果set_prefix為 True,則設置線程本地 urlresolvers 腳本前綴。

所以基本上為了確保設置已經完成,我們可以檢查應用程序是否准備就緒並配置了設置

from django.apps import apps
from django.conf import settings

if not apps.ready and not settings.configured:
    django.setup()

我在兩個生產 CLI python 包中工作過,在console_scripts顯式調用django.setup()

您應該注意的最重要的事情是env路徑中的DJANGO_SETTINGS_MODULE

你可以在 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()

因為我喜歡無條件代碼,所以我使用這個解決方案。 就像在 django 文檔中一樣,但是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()

設置.py:

    'console_scripts': [
        'say_thank_you=myapp.do_good_stuff_main:say_thank_you_main',
    ...

這是我目前的解決方案。 歡迎反饋。 有什么需要改進的嗎?

在 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。 多次導入一個模塊只會運行一次。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM