Доступ к URL домена (и порта) в файле settings.py при разработке на локальном хосте

Как динамически получить доступ к URL доменного имени в settings.py файле Django? (т.е. "http://localhost:8000")

Я пытаюсь перезаписать пакет CDN, пока интернет недоступен во время разработки, и хочу указать на локальный файл в каталоге static files. Хотя os.path.join(BASE_DIR, "path/to/local.file") должен работать, это зависит от контекста, от того, какое приложение/url (то есть "http://localhost:8000/app/static/css/bootstrap.min.css "), а не только основного домена со статическим расположением файла, добавленного к стартовому серверу с ./manage.py runserver 0:8000 (т.е. "http://localhost:8000/static/css/bootstrap.min.css").

Примечания:

  • Поскольку это находится в settings.py, я не могу загрузить ни одно приложение или reverse из-за ошибки *** django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
  • .
  • Я не в шаблоне, поэтому я не могу использовать static url
  • .
  • статическое определение не позволит использовать различные загрузки портов при запуске через ./manage.py runserver 0:8000
  • .
  • settings.py по сути является модулем python, но как получить домен внутри него?

В основном в файле settings.py:

# If in local dev
if "RDS_DB_NAME" not in os.environ:
    # the setting for the package I am pointing to a local version
    BOOTSTRAP5 = {
        "css_url": {
            ### dynamically get domain here ###
            # "href": os.path.join(LOCAL_DIR, "static/css/bootstrap.min.css"),
            "href": "static/css/bootstrap.min.css",
        }

Я никогда не находил способа узнать подробности о слушателе Django.

Канонический способ иметь разные настройки в разных окружениях - это иметь разные файлы настроек, а затем установить переменную окружения DJANGO_SETTINGS_MODULE, чтобы контролировать, какой из них используется.

Вы не можете получить доступ к домену в settings.py. Когда вы запускаете ./manage.py runserver 0:8000, вы говорите Django слушать порт 8000 любого локального хоста. Но вы не можете сказать с этой машины, какие запросы придут на эту машину. Например, вы можете настроить DNS на отправку запросов www.domain1.com и www.domain2.com на эту машину, которая с вашей точки зрения выглядит как localhost. Таким образом, вы не можете узнать "домен", пока не придет запрос.

Однако у вашей машины есть локальное имя машины, которое вы можете узнать из settings.py. Разные ОС делают это по-разному, но на Mac вы можете получить его с помощью scutil --get LocalHostName, а на других Unix - cat /etc/hostname.

Крис Керви прав в том, что канонический способ различать окружения - это разные файлы настроек. Большинство разработчиков различают локальную и рабочую среды, но вы предлагаете третью: локальную без доступа в интернет.

Есть 2 шага, чтобы заставить это работать.

Определите, когда использовать окружение "локальный без интернета".

Журнальный способ (и самый простой способ, IMO) сделать это - с помощью переменной окружения. Есть много способов сделать это. Например, вы можете установить LOCAL_NO_INTERNET=True в окружении и затем проверять эту переменную в любое время, когда вам нужно сделать что-то особенное в вашем коде.

Если вам действительно нужно определить это автоматически, вы можете:

  1. Запросите имя локальной машины (имя машины, а не домена, как описано выше)
  2. Проверьте, совпадает ли имя с именем вашей локальной dev-машины (чтобы не делать это в prod и т.д.)
  3. Проверьте, нет ли у вас интернета (пинг google.com или что-то подобное и посмотрите, успешно ли он возвращается или отрубается)

Я не рекомендую такой подход; существует множество крайних случаев. Кроме того, вы, вероятно, можете определить для себя, хотите ли вы находиться в окружении "локально без интернета" и установить переменную окружения вручную.

Предоставление кэшированных файлов, обычно предоставляемых CDN

Я думаю, что самый простой способ, хотя и немного многословный, заключается в том, чтобы поместить оператор if в ваши шаблоны, чтобы нацелить либо CDN, либо вашу локальную версию (обратите внимание, что вам придется передать LOCAL_NO_INTERNET в контексте представления):

{% if LOCAL_NO_INTERNET %}
  <script src="{% static "cdncache/bootstrap.min.js" %}"></script>
{% else %}
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="..." crossorigin="anonymous"></script>
{% endif %}

Или вы можете сделать что-то более сложное, например, промежуточное ПО, чтобы как-то заменить ссылки на CDN.

Я бы предложил вместо определения нового окружения "локально без интернета" изменить вашу локальную настройку так, чтобы она всегда предполагала "локально без интернета". CDN должен ускорить запросы в продакшене, но не принесет вам много пользы в локальной разработке по сравнению с постоянным использованием вашей собственной версии этих файлов.

Вернуться на верх