Доступ к 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
в окружении и затем проверять эту переменную в любое время, когда вам нужно сделать что-то особенное в вашем коде.
Если вам действительно нужно определить это автоматически, вы можете:
- Запросите имя локальной машины (имя машины, а не домена, как описано выше)
- Проверьте, совпадает ли имя с именем вашей локальной dev-машины (чтобы не делать это в prod и т.д.)
- Проверьте, нет ли у вас интернета (пинг 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 должен ускорить запросы в продакшене, но не принесет вам много пользы в локальной разработке по сравнению с постоянным использованием вашей собственной версии этих файлов.