Как я могу получить URL (с протоколом и доменом) в Django (без запроса)?

Я хочу отправить почту в задание cron. Почта должна содержать ссылку на мое приложение.

В задании cron у меня нет объекта запроса и я не могу использовать request.build_absolute_uri().

AFAIK рамки сайта могут помочь здесь. Но не дает мне протокол (http vs https)?

Мое приложение многократно используется и иногда размещается на http, а иногда и на сайтах https.

Обновление

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

Связанная проблема: https://code.djangoproject.com/ticket/16734

Ответы

Ответ 1

Для этого есть специальный стандартный модуль - Site Framework. В нем добавлена ​​модель сайта, в которой описывается конкретный сайт. Эта модель имеет поле domain для домена проекта и name - общедоступное имя сайта.

Вы связываете свои модели с сайтами. Например:

from django.db import models
from django.contrib.sites.models import Site

class Article(models.Model):
    headline = models.CharField(max_length=200)
    # ...
    site = models.ForeignKey(Site, on_delete=models.CASCADE)

Когда вам нужно создать URL-адрес для объекта, вы можете использовать что-то вроде следующего кода:

   >>> from django.contrib.sites.models import Site
   >>> obj = MyModel.objects.get(id=3)
   >>> obj.get_absolute_url()
   '/mymodel/objects/3/'
   >>> Site.objects.get_current().domain
   'example.com'
   >>> 'https://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url())
   'https://example.com/mymodel/objects/3/'

Таким образом, вы можете иметь несколько доменов и контент, распространяемый между ними. Даже если у вас есть только один домен, я рекомендую использовать его для достижения хорошего стандартного удобного способа сохранения настроек домена.

Installatioin довольно просто:

  • Добавьте 'django.contrib.sites' в настройку INSTALLED_APPS.

  • Определите параметр SITE_ID:

     SITE_ID = 1
    
  • Запустить миграцию.

Ответ 2

TL; DR: Нет никакого "стандартного" метода "Django-ish", но принцип DRY, продвигаемый платформой, предполагает единое хранилище конфигурации, поэтому пользовательская настройка кажется быть хорошим способом.

По умолчанию Django может обслуживать любое количество доменов из одного экземпляра, а HTTP-запрос (точнее, заголовок HTTP_HOST) - это единственное, что Django использует для определения текущего хоста. Поскольку ваши задания cron явно выходят из цикла HTTP, вы должны хранить свой домен где-то в настройках...

# settings.py
DEFAULT_DOMAIN = 'https://foobar.com'
# or, depending on your configuration:
DEFAULT_DOMAIN = 'https://{}'.format(ALLOWED_HOSTS[0])

... с крошечным процессором контекста, чтобы упростить обработку шаблонов:

# yourapp/context_processors.py
from django.conf import settings

def default_domain(request):
    return {'default_domain': settings.DEFAULT_DOMAIN}

... и затем используйте его в своих письмах:

# yourapp/templates/email/body.html
<a href="{{ default_domain }}{% url 'target' %}">Click here</a>

В качестве альтернативы вы можете использовать фреймворк sites, но если вы обслуживаете один домен, решение на основе настроек выглядит намного проще и чище для меня.