Как я могу получить доменное имя моего сайта в шаблоне Django?

123

Как получить доменное имя моего текущего сайта из шаблона Django? Я пробовал искать в теге и фильтрах, но ничего там.

Теги:
django-templates

13 ответов

52
Лучший ответ

Я думаю, что вы хотите получить доступ к контексту запроса, см. RequestContext.

  • 0
    если вы имеете в виду request.url, вы получите только путь минус домен
  • 115
    request.META['HTTP_HOST'] дает вам домен. В шаблоне это будет {{ request.META.HTTP_HOST }} .
Показать ещё 6 комментариев
80

Если вы хотите, чтобы фактический заголовок хоста HTTP, см. комментарий Даниэля Роземана к ответу @Phsiao. Другой альтернативой является использование структуры contrib.sites, вы можете установить каноническое доменное имя для сайта в базе данных (сопоставление запрос домена в файл настроек с соответствующим SITE_ID - это то, что вам нужно сделать самостоятельно через настройку вашего веб-сервера). В этом случае вы ищете:

from django.contrib.sites.models import Site

current_site = Site.objects.get_current()
current_site.domain

вам нужно поставить объект current_site в контекст шаблона самостоятельно, если вы хотите его использовать. Если вы используете его повсюду, вы можете упаковать его в обработчик контекста шаблона.

  • 2
    Для того, чтобы уточнить , для кого - то , кто имеет те же проблемы , как я: убедитесь , что ваш SITE_ID параметр равен id атрибут текущего сайта Sites приложения (вы можете найти id в Sites панели администратора). Когда вы вызываете get_current , Django берет ваш SITE_ID и возвращает объект Site с этим идентификатором из базы данных.
57

Я обнаружил метод {{ request.get_host }}.

  • 7
    Обратите внимание, что в этом ответе есть те же проблемы, что и в подходе Даниэля Розмана (его можно подделать), но он, безусловно, более полон, когда к хосту HTTP_X_FORWARDED_HOST через HTTP-прокси или балансировщик нагрузки, поскольку он учитывает HTTP-заголовок HTTP_X_FORWARDED_HOST .
  • 3
    Использование: "// {{request.get_host}} / что-нибудь / еще / вы / хотите" ... Обязательно заполните настройку ALLOWED_HOSTS (см. Docs.djangoproject.com/en/1.5/ref/settings/#allowed -хосты ).
Показать ещё 2 комментария
55

Дополняя Карла Мейера, вы можете создать такой контекстный процессор, как это:

module.context_processors.py

from django.conf import settings

def site(request):
    return {'SITE_URL': settings.SITE_URL}

локальные settings.py

SITE_URL = 'http://google.com' # this will reduce the Sites framework db call.

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
 )

шаблоны, возвращающие экземпляр контекста, URL-адрес сайта {{SITE_URL}}

вы можете написать свой собственный rutine, если хотите обрабатывать субдомены или SSL в процессоре контекста.

  • 1
    для контекстно-процессорного подхода
  • 0
    Я пробовал это решение, но если у вас есть несколько поддоменов для одного приложения, это не практично, я нашел очень полезный ответ от danbruegge
21

Изменение используемого процессора контекста:

from django.contrib.sites.shortcuts import get_current_site
from django.utils.functional import SimpleLazyObject


def site(request):
    return {
        'site': SimpleLazyObject(lambda: get_current_site(request)),
    }

Оболочка SimpleLazyObject гарантирует, что вызов БД происходит только тогда, когда шаблон фактически использует объект site. Это удаляет запрос с страниц администратора. Он также кэширует результат.

и включить его в настройки:

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
)

В шаблоне вы можете использовать {{ site.domain }} для получения текущего имени домена.

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

def site(request):
    site = SimpleLazyObject(lambda: get_current_site(request))
    protocol = 'https' if request.is_secure() else 'http'

    return {
        'site': site,
        'site_root': SimpleLazyObject(lambda: "{0}://{1}".format(protocol, site.domain)),
    }
  • 0
    Вам не нужно использовать SimpleLazyObject здесь, потому что лямбда не будет вызываться, если в любом случае ничто не обращается к «сайту».
  • 0
    Если вы удалите SimpleLazyObject , каждый RequestContext вызовет get_current_site() и, следовательно, выполнит запрос SQL. Оболочка гарантирует, что переменная оценивается только тогда, когда она фактически используется в шаблоне.
Показать ещё 4 комментария
14

Я знаю, что этот вопрос старый, но я наткнулся на него, пытаясь найти настоящий домен.

def myview(request):
    domain = request.build_absolute_uri('/')[:-1]
    # that will build the complete domain: http://foobar.com
  • 4
    build_absolute_uri задокументировано здесь .
11

Быстро и просто, но не хорошо для производства:

(в представлении)

    request.scheme               # http or https
    request.META['HTTP_HOST']    # example.com
    request.path                 # /some/content/1/

(в шаблоне)

{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}

Обязательно используйте RequestContext, что имеет место, если вы используете render.

Не доверяйте request.META['HTTP_HOST'] в процессе производства: эта информация поступает из браузера. Вместо этого используйте ответ @CarlMeyer

  • 0
    Я отвечаю за этот ответ, но я получил ошибку при попытке использовать request.scheme . Возможно, доступно только в новых версиях Django.
  • 0
    @MattCremeens request.scheme был добавлен в Django 1.7.
Показать ещё 1 комментарий
8

{{ request.get_host }} должен защищать от атак HTTP Host header при использовании вместе с настройкой ALLOWED_HOSTS (добавлен в Django 1.4.4).

Обратите внимание, что {{ request.META.HTTP_HOST }} не имеет такой защиты. См. docs:

allowed_hosts

Список строк, представляющих имена хоста/домена, которые может обслуживать этот сайт Django. Это мера безопасности, предотвращающая HTTP-атаки заголовка хоста, которые возможны даже при многих, казалось бы, безопасных конфигурациях веб-сервера.

... Если заголовок Host (или X-Forwarded-Host, если USE_X_FORWARDED_HOST включен) не соответствует никакому значению в этом списке, метод django.http.HttpRequest.get_host() будет поднимать SuspiciousOperation.

... Эта проверка применяется только через get_host(); если ваш код обращается к заголовку узла непосредственно из request.META, вы обходите эту защиту.


Что касается использования request в вашем шаблоне, вызовы функции преобразования шаблона имеют изменено в Django 1.8, так что у вас больше нет для прямой обработки RequestContext.

Здесь, как визуализировать шаблон для представления, используя функцию быстрого доступа render():

from django.shortcuts import render

def my_view(request):
    ...
    return render(request, 'my_template.html', context)

Здесь, как визуализировать шаблон для электронной почты, который IMO является более распространенным случаем, когда вы хотите получить значение хоста:

from django.template.loader import render_to_string

def my_view(request):
    ...
    email_body = render_to_string(
        'my_template.txt', context, request=request)

Здесь приведен пример добавления полного URL-адреса в шаблон электронной почты; request.scheme должен получить http или https в зависимости от того, что вы используете:

Thanks for registering! Here your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
8

Я использую специальный тег шаблона. Добавить, например. <your_app>/templatetags/site.py:

# -*- coding: utf-8 -*-
from django import template
from django.contrib.sites.models import Site

register = template.Library()

@register.simple_tag
def current_domain():
    return 'http://%s' % Site.objects.get_current().domain

Используйте его в шаблоне следующим образом:

{% load site %}
{% current_domain %}
  • 0
    Есть ли какой-то конкретный недостаток этого подхода? Помимо звонка на сайт БД по каждому запросу.
  • 0
    @ kicker86 Я не знаю ни одного. get_current - это документированный метод: docs.djangoproject.com/en/dev/ref/contrib/sites/…
Показать ещё 1 комментарий
2

Как и пользовательский ответ panchicore, это то, что я сделал на очень простом веб-сайте. Он предоставляет несколько переменных и делает их доступными в шаблоне.

SITE_URL будет содержать значение, подобное example.com
SITE_PROTOCOL будет иметь значение, подобное http или https
SITE_PROTOCOL_URL будет содержать значение, подобное http://example.com или https://example.com
SITE_PROTOCOL_RELATIVE_URL будет содержать значение, подобное //example.com.

модуль /context _processors.py

from django.conf import settings

def site(request):

    SITE_PROTOCOL_RELATIVE_URL = '//' + settings.SITE_URL

    SITE_PROTOCOL = 'http'
    if request.is_secure():
        SITE_PROTOCOL = 'https'

    SITE_PROTOCOL_URL = SITE_PROTOCOL + '://' + settings.SITE_URL

    return {
        'SITE_URL': settings.SITE_URL,
        'SITE_PROTOCOL': SITE_PROTOCOL,
        'SITE_PROTOCOL_URL': SITE_PROTOCOL_URL,
        'SITE_PROTOCOL_RELATIVE_URL': SITE_PROTOCOL_RELATIVE_URL
    }

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
 )

SITE_URL = 'example.com'

Затем на ваших шаблонах используйте их как {{ SITE_URL }}, {{ SITE_PROTOCOL }}, {{ SITE_PROTOCOL_URL }} и {{ SITE_PROTOCOL_RELATIVE_URL }}

0

Как насчет этого подхода? Работает на меня. Он также используется в django-регистрации.

def get_request_root_url(self):
    scheme = 'https' if self.request.is_secure() else 'http'
    site = get_current_site(self.request)
    return '%s://%s' % (scheme, site)
0
from django.contrib.sites.models import Site
if Site._meta.installed:
    site = Site.objects.get_current()
else:
    site = RequestSite(request)
-2

Вы можете использовать {{ protocol }}://{{ domain }} в своих шаблонах, чтобы получить свое доменное имя.

  • 0
    -1 потому что не сработало, нужно ли менять settings.py?
  • 0
    Я не думаю, что @Erwan замечает, что это зависит от нестандартного обработчика контекста запроса.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню