Подтвердить что ты не робот

Sphinx и повторно используемые приложения Django

проблема

При попытке создать документацию sphinx для повторно используемого приложения Django я ударил по следующему snafoo. Когда sphinx анализирует код model.py это мешает его код, пытающийся получить доступ к настройкам проекта Django. Поскольку это автономное/многоразовое приложение, нет основного проекта, обеспечивающего эти параметры, т. ROOT/PROJECT/PROJECT/settings.py Нет файла ROOT/PROJECT/PROJECT/settings.py.

Настроить

В интересах ясности вот что я сделал. Перейдите к тому, что будет обычной папкой проекта cd ROOT/PROJECT и создайте приложение django-admin startapp APPLICATION которое создает следующую структуру

/ROOT/
  /PROJECT/
    /APPLICATION/ 
      admin.py
      apps.py
      models.py
      tests.py
      views.py

Примечание. Нет файлов /ROOT/PROJECT/PROJECT/*.py потому что я не /ROOT/PROJECT/PROJECT/*.py к корневому корневому каталогу cd root и не создавал проект с помощью django-admin createproject как обычно.

Затем создается документация sphinx, которая spinx-quickstart docs следующую дополнительную структуру.

/ROOT/
  /PROJECT/
    /docs/
      /source/ 
        ...
        conf.py
      make.bat

То есть документы создаются рядом с APPLICATION.

Вопрос

Что я могу разместить в conf.py для правильной загрузки приложения без файла settings.py?

Домашнее задание

В попытке решить это я просмотрел ряд SO-вопросов, блогов и Django Docs и не нашел сжатого решения. Поскольку это было задано несколько раз до этого, я хотел бы мотивировать, что он не будет закрыт как дубликат, если ответ в предлагаемом дубликате использует один из этих фрагментов в качестве решения.

  • AppRegistryNotReady с AppRegistryNotReady

    from django.conf import settings
    settings.configure()
    
  • Подобно первому методу отказа, т.е. испускает AppRegistryNotReady

    from django.conf import settings
    settings.configure()
    settings.INSTALLED_APPS += ['fintech']
    
  • Ошибка при ImproperlyConfigured

    import django
    django.setup()
    
  • Существует действительно старое решение, в котором упоминается устаревшая setup_environ

    from django.core.management import setup_environ
    from django.conf import settings
    settings.configure()
    setup_environ(settings)
    
  • Это также любимый ответ, но он не работает, если нет файла settings.py.

    import django
    os.environ['DJANGO_SETTINGS_MODULE'] = 'PROJECT.settings'
    django.setup()
    

Я также задал этот вопрос довольно подробный, поскольку связанные с ним вопросы относительно SO довольно кратки и не особенно полезны. Если это поможет, я использую Django 1.10.

Обновить

С тех пор я обнаружил, что если один из них импортирует свою функцию setup из setuptools сравнению с distutils.core то можно вызвать скрипт установки для компиляции своей документации, как в python setup.py build_sphinx -b BUILDER Вероятно, лучше повторить запрос при вызове setup.py над docs/conf.py через make.bat или MakeFile предоставленный Sphinx.

Я подозреваю, что результат будет схожим, а именно включать предоставленные ответы в docs/conf.py или, альтернативно, в setup.py, оба должны быть вызваны в рамках одного сеанса Python.

4b9b3361

Ответ 1

Если вы не хотите, чтобы ваша документация зависела от проекта "demo", вы можете вручную создать настройки в conf.py В разделе настройки пути:

import django
from django.conf import settings
import os
import sys

# add path to sys.path (this might be different in your project)
sys.path.insert(0, os.path.abspath('..'))

# pass settings into configure
settings.configure(
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'my_reusable_app',
        'any_other_dependencies',
    ]
)

# call django.setup to load installed apps and other stuff
django.setup()

# ... continue with rest of conf.py

Теперь Sphinx может импортировать модули приложения без settings.py проекта. Другие параметры можно передать в settings.configure().

Ответ 2

Это не ответ на вопрос

Что я могу разместить в conf.py для правильной загрузки приложения без файла settings.py?

но альтернативный подход: поместите минимальный, жизнеспособный проект Django в пакет многоразового использования. Его можно использовать для примеров внедрения, тестирования (включая покрытие кода), разработки и создания doc. Мы делаем это именно так в частных хранилищах нашей компании, и я видел несколько пакетов django на github, которые тоже делают это.

Типичная структура моих пакетов выглядит так:

docs
├── conf.py
├── ... rst files
mypackage          # the actual package
mypackage_demo     # the Django project
├── .coveragerc
├── manage.py
├── settings.py
README.rst
requirements.txt
setup.py

В docs/conf.py я проверяю переменную среды настроек и использую демонстрационный проект, если не указано:

if not os.environ.get('DJANGO_SETTINGS_MODULE'):
    os.environ['DJANGO_SETTINGS_MODULE'] = 'mypackage_demo.settings'
django.setup()

Таким образом, вы можете создать документы с помощью другого проекта, установив DJANGO_SETTINGS_MODULE среды DJANGO_SETTINGS_MODULE перед вызовом sphinx.

settings.py просто содержит минимальную конфигурацию, необходимую для запуска приложения. Абсолютным минимумом для работы Django являются следующие:

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY = ''
INSTALLED_APPS = [
    'mypackage'
]

Ответ 3

У меня была такая же проблема с Django 1.11 и Sphinx 1.5.5. Мне не удалось заставить его работать должным образом, и все решения, о которых вы говорили выше, тоже не работали. В конце концов я решил это, добавив это в свой Sphinx conf.py:

import sys, os

project_path = os.path.abspath('.')
# For Django to know where to find stuff.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_project.settings")
sys.path.append(project_path)

# For settings.py to load.
os.chdir(project_path)

# For the models to load.
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()