Як отримати доменне ім'я мого поточного сайту з шаблону 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 }}
поточне ім'я домену.
редагувати: для підтримки перемикання протоколів також використовуйте:
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 , у тому випадку, якщо ви використовуєте візуалізацію .
Не довіряйте request.META['HTTP_HOST']
виробництву: ця інформація надходить із браузера. Замість цього скористайтеся відповіддю @ CarlMeyer
request.scheme
. Можливо, доступний лише в новіших версіях джанго.
request.scheme
додано в Django 1.7.
{{ request.get_host }}
має захищати від атаки заголовка HTTP Host при використанні разом із ALLOWED_HOSTS
налаштуваннями (додано в Django 1.4.4).
Зауважте, що {{ request.META.HTTP_HOST }}
не має однакового захисту. Дивіться документи :
ALLOWED_HOSTS
Список рядків, що представляють імена хостів / доменів, якими може слугувати цей сайт Django. Це захід безпеки для запобігання атакам заголовка HTTP Host , які можливі навіть у багатьох конфігураціях веб-сервера.
... Якщо
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
матиме значення, подібне до example.com
SITE_PROTOCOL
такого, якhttp
або https
SITE_PROTOCOL_URL
містило б таке значення, як http://example.com
або https://example.com
SITE_PROTOCOL_RELATIVE_URL
містило б таке значення //example.com
.
module / 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}}
Що з таким підходом? Працює для мене. Він також використовується при реєстрації джанго .
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 }}
.