Как получить доменное имя моего текущего сайта из шаблона 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 }}
.