Получение данных о хосте в любой части кода

Когда у нас есть экземпляр объекта запроса, получить из него имя хоста проблем не составляет. Объект HttpRequest, содержащий запрос, для данных целей включает в себя специальный метод - get_host(). И из любого view мы можем к нему спокойно обращаться. В отличии от прямого использования данных в request.META, get_host более универсален.  С ним вы получите правильное имя даже в случае использования прокси, меняющего заголовки в META запроса.

# some_app/views.py
def some_view(request):
...
host = request.get_host()
# Для получения порта сервера используем
# метод get_port() объекта запроса.
port = request.get_port()
...

Внутри view это будет работать всегда. За исключением ситуаций, когда ваш хост скрыт не за одним, а за чередой проксирующах серверов. В этом случае потребуется видоизменение заголовков этих прокси. Но об этом как-нибудь поговорим отдельно. Сейчас у нас другая тема.

Другая ситуация: имя домена нужно получить за пределами view. Например, в обработчиках своих специфических сигналов. Или вот еще нагляднее пример: пинг гугла об обновлении при создании нового поста. И тут уже не так все очевидно.

Первым напрашивается решение тупо захардкодить имя хоста в settings.py. Это решение так себе. Вы же не пишете для каждого нового своего проекта весь функционал с нуля? Значит стоит упростить переиспользование уже написанного ранее кода. Забивание settings кастомными константами по каждому чиху этот процесс лишь усложняет. И обычно затрудняет процесс тестирования. В общем - не советую. Особенно, когда в API Django есть и на этот случай инструменты. Да, для них тоже нужны записи в settins.py. Но взамен вы получите несравнимо больше, нежели от просто еще одной строки в настройках.

Использование встроенного приложения Sites

Есть такой набор полезностей, живущих в django.contrib.sites. Полезности эти призваны упростить жизнь разработчика на Django, в случае, когда на одной инсталляции фреймворка "вертится" не один, а несколько сайтов. Но и в случае с единственным не вижу серьезных причин отказываться от этого приложения. Оверхед будет вполне оправдан удобством получения нужных данных везде, где это необходимо. Как и самими данными: ведь это может быть далеко не только название домена.

Изначально приложение не установлено. Что бы воспользоваться им, следует добавить в список INSTALLED_APPS соответствующий пункт. И обозначить идентификатор текущего сайта. После чего - запустить миграции: ./manage.py migrate.

# settings.py
...
INSTALLED_APPS = [
...
'django.contrib.sites',
...
]
SITE_ID = 666 # Цифирь, идентифицирующая конкретный сайт. 
              # Какая именно - на ваше усмотрение.

Теперь, когда приложение sites у нас задействовано, мы можем использовать его везде, где будут нужны его возможности. Применительно к обсуждаемой теме - отличный пример такого использования есть в коде "встроенного" приложения для построения карты сайта. В той его части, где реализован пинг для Google об изменениях в sitemap.xml. Хост мы получаем из свойства domain объекта Sites.

# Модуль django.contrib.sitemaps
...some_imports...
...
   
# Основная функция, реализующая пинг.
def ping_google(sitemap_url=None, ping_url=PING_URL):
...
# Интересующий нас пример лежит в 
# вызываемой приватной функции _get_sitemap_full_url()
sitemap_full_url = _get_sitemap_full_url(sitemap_url)
...
   
def _get_sitemap_full_url(sitemap_url):
# Проверка на установленное приложение sites.
if not django_apps.is_installed('django.contrib.sites'):
raise ImproperlyConfigured("ping_google requires django.contrib.sites, \
                            which isn't installed.")
  
if sitemap_url is None:
try:
sitemap_url = reverse('django.contrib.sitemaps.views.index')
except NoReverseMatch:
try:
# Next, try for the "global" sitemap URL.
sitemap_url = reverse('django.contrib.sitemaps.views.sitemap')
except NoReverseMatch:
pass
  
if sitemap_url is None:
raise SitemapNotFound("You didn't provide a sitemap_url, \
      and the sitemap URL couldn't be auto-detected.")
  
# Создание модели Site
Site = django_apps.get_model('sites.Site')
# Получение данных о текущем сайте.
current_site = Site.objects.get_current()
# Подстановка в результат хоста
# из экземпляра объекта Site - current_site.domain
return 'http://%s%s' % (current_site.domain, sitemap_url)