2016-09-26 13 views
9

Текущие документы Джанго сказать мне это:Как вызвать django.setup() в console_script?

django.setup() может быть вызван только один раз.

Поэтому избегайте применения многоразовой логики приложения в автономных сценариях, поэтому вам нужно импортировать из сценария в другое место приложения. Если вы не можете избежать этого, поставить вызов django.setup() внутри, если блок:

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

Источник: Calling django.setup() is required for “standalone” Django usage

Я использую точки входа в setup.py. Таким образом, у меня нет __name__ == '__main__'.

Вопрос

Как обеспечить django.setup() получает только раз, если вы используете console_scripts?

Куда следует поместить django.setup()?

фон

Фактическая ошибка у меня есть: Django зависает. Вот почему: https://code.djangoproject.com/ticket/27176

Я хочу передать свое приложение в текущую версию django. Переход к команде управления не является опцией, поскольку другие (сторонние приложения) полагаются на наличие моих консольных скриптов.

+0

Какая ошибка? – e4c5

+2

Возможно, вы также можете упомянуть, что вы пытаетесь сделать очень часто [пользовательская команда управления] (https://docs.djangoproject.com/en/1.10/howto/custom-management-commands/), возможно, это более чистое решение, когда вы делаете что-то, что нуждается в окружении джанго. –

+0

@BernhardVallant Я обновил вопрос. Переход на команду управления не является вариантом. – guettli

ответ

0

Так как я люблю условие меньше кода, я использую это решение. Это похоже на django docs, но избегается ulgy 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', 
    ... 

Это мое текущее решение. Приветствуем Ffeeback. Есть что улучшить?

+0

Итак, в основном ваше решение состоит в том, чтобы сделать то, что я предложил в своем комментарии к вашему вопросу. – Louis

+0

@ Луис да. Еще одна проблема: 'do_good_stuff_main.py' будет вызывать' django.setup() 'во второй раз, если он будет импортирован для тестирования. – guettli

7

имел такую ​​же проблему (или что-то подобное). Я решил ее делать:

[Warning: грязный раствор]

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

таким образом, он будет вызываться только один раз, даже если он импортируется несколько раз

2

Здесь https://docs.djangoproject.com/en/1.10/_modules/django/#setup мы можем увидеть, что django.setup на самом деле делает.

Конфигурирование настроек (это происходит как побочный эффект доступа к первый параметр), настроить ведение журнала и заполнение реестра приложения. Установите префикс сценария для локального urlresolvers, если set_prefix является True.

Так в основном, чтобы гарантировать, что установка уже было сделано, мы можем проверить, если приложения готовы и параметры настроены

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

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

Что произойдет, если вы удалите «if not ...». Другими словами, что произойдет, если django.setup() вызывается дважды? – guettli

+0

@guettli Вероятно, это приведет к сбою с 'raise RuntimeError ('Настройки уже настроены.')'. Потому что он попытается настроить параметры еще раз. Но apps.populate не должен иметь никаких проблем, потому что он делает это 'if self.ready: return' –

+0

. Не должно ли условие быть просто' if not apps.ready: '? – Hussain

1

Я работал в двух продуктовых пакетах Python с явным вызовом django.setup() в console_scripts.

Главное, что вы должны отметить, это DJANGO_SETTINGS_MODULE в env Путь.

Вы можете установить это значение в сценарии оболочки или даже загрузить настройки по умолчанию в свой скрипт 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()