Как получить доменное имя моего текущего сайта из шаблона Django? Я пытался посмотреть в тег и фильтры, но ничего там.
Как получить доменное имя моего текущего сайта из шаблона Django? Я пытался посмотреть в тег и фильтры, но ничего там.
Ответы:
Я думаю, что вы хотите, чтобы иметь доступ к контексту запроса, см. RequestContext.
Host:заголовок и получает ответ с поддельным доменом где-то на странице, как это создает дыру в безопасности? Я не понимаю, чем это отличается от того, что пользователь берет сгенерированный HTML и модифицирует себя перед тем, как передать его в свой собственный браузер.
Если вам нужен фактический заголовок HTTP Host, см. Комментарий Даниэля Роземана к ответу @ Phsiao. Другой вариант - если вы используете платформу contrib.sites , вы можете установить каноническое доменное имя для сайта в базе данных (сопоставление домена запроса с файлом настроек с правильным SITE_ID - это то, что вы должны сделать самостоятельно через свой настройка веб-сервера). В этом случае вы ищете:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
вам нужно будет поместить объект current_site в контекст шаблона самостоятельно, если вы хотите его использовать. Если вы используете его повсеместно, вы можете упаковать его в процессор контекста шаблона.
SITE_IDнастройки соответствуют idатрибуту текущего сайта в приложении «Сайты» (вы можете найти его idв админ-панели «Сайты»). Когда вы звоните get_current, Django берет ваш SITE_IDи возвращает Siteобъект с этим идентификатором из базы данных.
print("get_current_site: ", get_current_site(request)) print("absolute uri: ", request.build_absolute_uri()) print("HTTP_HOST: ", request.META['HTTP_HOST']) get_current_site: localhost:8001 absolute uri: http://localhost:8001/... HTTP_HOST: localhost:8001
Я открыл {{ request.get_host }}метод.
HTTP_X_FORWARDED_HOSTзаголовок HTTP.
request.build_absolute_uri( docs.djangoproject.com/en/dev/ref/request-response/… )
В дополнение к Карлу Мейеру, вы можете создать контекстный процессор, например так:
from django.conf import settings
def site(request):
return {'SITE_URL': settings.SITE_URL}
SITE_URL = 'http://google.com' # this will reduce the Sites framework db call.
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
Вы можете написать свою собственную рутину, если хотите обрабатывать субдомены или SSL в контекстном процессоре.
Вариант контекстного процессора, который я использую:
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Обертка убеждается вызов DB происходит только тогда , когда шаблон фактически использует siteобъект. Это удаляет запрос со страниц администратора. Это также кеширует результат.
и включите его в настройках:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
В шаблоне вы можете использовать {{ site.domain }}для получения текущего доменного имени.
edit: для поддержки переключения протокола тоже используйте:
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)),
}
SimpleLazyObjectздесь, потому что лямбда не будет вызываться, если в любом случае ничто не заходит на сайт.
SimpleLazyObject, каждый RequestContextбудет вызывать get_current_site(), и, следовательно, выполнить запрос SQL. Оболочка гарантирует, что переменная оценивается только тогда, когда она фактически используется в шаблоне.
SimpleLazyObjectсделано для того, чтобы избежать переоценки функции, которая на самом деле не нужна, поскольку Siteобъект кэшируется.
from django.contrib.sites.shortcuts import get_current_site
Я знаю, что этот вопрос старый, но я наткнулся на него в поисках питонского способа получения текущего домена.
def myview(request):
domain = request.build_absolute_uri('/')[:-1]
# that will build the complete domain: http://foobar.com
build_absolute_uri задокументировано здесь .
Быстро и просто, но не подходит для производства:
(в представлении)
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
request.scheme. Возможно, доступно только в новых версиях Django.
request.schemeбыл добавлен в Django 1.7.
{{ request.get_host }}должен защищать от атак заголовка HTTP-хоста при использовании вместе с ALLOWED_HOSTSнастройкой (добавлено в Django 1.4.4).
Обратите внимание, что {{ request.META.HTTP_HOST }}не имеет такой же защиты. Смотрите документы :
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's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
Я использую пользовательский тег шаблона. Добавить к например <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 %}
get_currentэто документированный метод: docs.djangoproject.com/en/dev/ref/contrib/sites/…
'http://%s'может быть проблема в случае httpsподключения; Схема не является динамической в этом случае.
Подобно ответу пользователя panchicore, это то, что я сделал на очень простом веб-сайте. Он предоставляет несколько переменных и делает их доступными в шаблоне.
SITE_URLбудет содержать значение like example.com
SITE_PROTOCOLбудет содержать значение like http или https
SITE_PROTOCOL_URLбудет содержать значение like http://example.comили https://example.com
SITE_PROTOCOL_RELATIVE_URLбудет содержать значение like //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 }}
В шаблоне Django вы можете сделать:
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
django.template.context_processors.requestтакже [это руководство помогло] ( simpleisbetterthancomplex.com/tips/2016/07/20/… )
Если вы используете обработчик контекста «запрос» и используете платформу сайтов Django , и у вас установлено промежуточное программное обеспечение сайта (т.е. ваши настройки включают это):
INSTALLED_APPS = [
...
"django.contrib.sites",
...
]
MIDDLEWARE = [
...
"django.contrib.sites.middleware.CurrentSiteMiddleware",
...
]
TEMPLATES = [
{
...
"OPTIONS": {
"context_processors": [
...
"django.template.context_processors.request",
...
]
}
}
]
... тогда у вас будет requestобъект, доступный в шаблонах, и он будет содержать ссылку на текущий Siteдля запроса как request.site. Затем вы можете получить домен в шаблоне с помощью:
{{request.site.domain}}
Как насчет этого подхода? Работает для меня. Он также используется в 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)
localhostвы получите httpsсхему (она считается безопасной), которая не будет работать, если у вас есть статический URL (только http://127.0.0.1действительный, а не https://127.0.0.1). Так что это не идеально, когда все еще в разработке.
from django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
Вы можете использовать {{ protocol }}://{{ domain }}в своих шаблонах, чтобы получить доменное имя.
request.META['HTTP_HOST']дает вам домен. В шаблоне это было бы{{ request.META.HTTP_HOST }}.