Jak uzyskać nazwę domeny mojej bieżącej witryny z szablonu Django? Próbowałem poszukać w tagu i filtrach, ale nic tam nie ma.
Jak uzyskać nazwę domeny mojej bieżącej witryny z szablonu Django? Próbowałem poszukać w tagu i filtrach, ale nic tam nie ma.
Odpowiedzi:
Myślę, że chcesz mieć dostęp do kontekstu żądania, zobacz RequestContext.
Host:
nagłówek i otrzyma odpowiedź z fałszywą domeną gdzieś na stronie, w jaki sposób tworzy to lukę w zabezpieczeniach? Nie rozumiem, czym różni się to od tego, że użytkownik pobiera wygenerowany kod HTML i modyfikuje się przed przesłaniem go do własnej przeglądarki.
Jeśli chcesz uzyskać rzeczywisty nagłówek hosta HTTP, zobacz komentarz Daniela Rosemana na temat odpowiedzi @ Phsiao. Inną alternatywą jest to, że jeśli korzystasz z platformy contrib.sites , możesz ustawić kanoniczną nazwę domeny dla Witryny w bazie danych (mapowanie domeny żądania do pliku ustawień z odpowiednim SITE_ID jest czymś, co musisz zrobić samodzielnie za pośrednictwem konfiguracja serwera WWW). W takim przypadku szukasz:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
musiałbyś sam umieścić obiekt current_site w kontekście szablonu, jeśli chcesz go użyć. Jeśli używasz go wszędzie, możesz to spakować w procesorze kontekstu szablonu.
SITE_ID
ustawienie jest równe id
atrybutowi bieżącej witryny w aplikacji Witryny (można ją znaleźć id
w panelu administracyjnym Witryny). Kiedy dzwonisz get_current
, Django pobiera twój SITE_ID
i zwraca Site
obiekt z tym id z bazy danych.
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
Odkryłem {{ request.get_host }}
metodę.
HTTP_X_FORWARDED_HOST
nagłówek HTTP.
request.build_absolute_uri
( docs.djangoproject.com/en/dev/ref/request-response/ ... )
Uzupełniając Carla Meyera, możesz zrobić taki procesor kontekstu:
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",
....
)
możesz napisać własną rutynę, jeśli chcesz obsługiwać subdomeny lub SSL w procesorze kontekstu.
Odmiana używanego przeze mnie procesora kontekstu to:
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
Wrapper pilnuje wywołanie DB dzieje się tylko wtedy, gdy szablon faktycznie korzysta z site
obiektu. Spowoduje to usunięcie zapytania ze stron administratora. Zapisuje również wynik w pamięci podręcznej.
i uwzględnij to w ustawieniach:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
W szablonie możesz użyć, {{ site.domain }}
aby uzyskać aktualną nazwę domeny.
edycja: aby obsługiwać również przełączanie protokołów, użyj:
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
tutaj używać , ponieważ lambda nie zostanie wywołana, jeśli i tak nic nie uzyska dostępu do „witryny”.
SimpleLazyObject
, każdy RequestContext
zadzwoni get_current_site()
, a tym samym wykona zapytanie SQL. Opakowanie zapewnia, że zmienna jest oceniana tylko wtedy, gdy jest faktycznie używana w szablonie.
SimpleLazyObject
to na celu uniknięcie ponownej oceny funkcji, która nie jest tak naprawdę potrzebna, ponieważ Site
obiekt jest buforowany.
from django.contrib.sites.shortcuts import get_current_site
Wiem, że to pytanie jest stare, ale natknąłem się na nie, szukając pythonowego sposobu na uzyskanie bieżącej domeny.
def myview(request):
domain = request.build_absolute_uri('/')[:-1]
# that will build the complete domain: http://foobar.com
build_absolute_uri
jest udokumentowane tutaj .
Szybki i prosty, ale nie nadaje się do produkcji:
(w widoku)
request.scheme # http or https
request.META['HTTP_HOST'] # example.com
request.path # /some/content/1/
(w szablonie)
{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}
Pamiętaj, aby użyć RequestContext , co ma miejsce, jeśli używasz renderowania .
Nie ufaj request.META['HTTP_HOST']
produkcji: te informacje pochodzą z przeglądarki. Zamiast tego użyj odpowiedzi @ CarlMeyer
request.scheme
. Być może dostępne tylko w nowszych wersjach django.
request.scheme
został dodany w Django 1.7.
{{ request.get_host }}
powinien chronić przed atakami nagłówka HTTP Host, gdy jest używany razem z ALLOWED_HOSTS
ustawieniem (dodane w Django 1.4.4).
Pamiętaj, że {{ request.META.HTTP_HOST }}
nie ma takiej samej ochrony. Zobacz dokumentację :
ALLOWED_HOSTS
Lista ciągów znaków reprezentujących nazwy hostów / domen, które może obsługiwać ta witryna Django. Jest to środek bezpieczeństwa zapobiegający atakom nagłówka HTTP Host , które są możliwe nawet w przypadku wielu pozornie bezpiecznych konfiguracji serwera WWW.
... Jeśli
Host
nagłówek (lubX-Forwarded-Host
jeśliUSE_X_FORWARDED_HOST
jest włączony) nie pasuje do żadnej wartości na tej liście,django.http.HttpRequest.get_host()
metoda podniesieSuspiciousOperation
.... Ta walidacja ma zastosowanie tylko przez
get_host()
; jeśli Twój kod uzyskuje dostęp do nagłówka Hosta bezpośrednio odrequest.META
Ciebie, pomijasz to zabezpieczenie.
Jeśli chodzi o używanie request
w twoim szablonie, wywołania funkcji renderującej szablon zmieniły się w Django 1.8 , więc nie musisz już obsługiwać RequestContext
bezpośrednio.
Oto jak wyrenderować szablon widoku za pomocą funkcji skrótu render()
:
from django.shortcuts import render
def my_view(request):
...
return render(request, 'my_template.html', context)
Oto jak renderować szablon wiadomości e-mail, który IMO jest najczęstszym przypadkiem, w którym chcesz uzyskać wartość hosta:
from django.template.loader import render_to_string
def my_view(request):
...
email_body = render_to_string(
'my_template.txt', context, request=request)
Oto przykład dodawania pełnego adresu URL w szablonie wiadomości e-mail; request.scheme powinien otrzymać http
lub w https
zależności od tego, czego używasz:
Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
Używam niestandardowego tagu szablonu. Dodaj np . <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
Użyj go w szablonie takim jak ten:
{% load site %}
{% current_domain %}
get_current
jest udokumentowaną metodą: docs.djangoproject.com/en/dev/ref/contrib/sites/…
'http://%s'
może być problem w przypadku https
połączenia; schemat nie jest dynamiczny w tym przypadku.
Podobnie jak w przypadku odpowiedzi użytkownika panchicore, oto co zrobiłem na bardzo prostej stronie internetowej. Udostępnia kilka zmiennych i udostępnia je w szablonie.
SITE_URL
trzymałby wartość podobną do example.com
SITE_PROTOCOL
trzymałby wartość podobną http
lub https
SITE_PROTOCOL_URL
trzymałby wartość podobną http://example.com
lub https://example.com
SITE_PROTOCOL_RELATIVE_URL
trzymałby wartość podobną //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'
Następnie na szablonach, należy je jak {{ SITE_URL }}
, {{ SITE_PROTOCOL }}
, {{ SITE_PROTOCOL_URL }}
i{{ SITE_PROTOCOL_RELATIVE_URL }}
W szablonie Django możesz:
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
django.template.context_processors.request
także [ten poradnik pomógł] ( simpleisbetterthancomplex.com/tips/2016/07/20/… )
Jeśli używasz procesora kontekstu „żądania” i korzystasz ze struktury witryn Django i masz zainstalowane oprogramowanie pośrednie witryny (tj. Twoje ustawienia obejmują te):
INSTALLED_APPS = [
...
"django.contrib.sites",
...
]
MIDDLEWARE = [
...
"django.contrib.sites.middleware.CurrentSiteMiddleware",
...
]
TEMPLATES = [
{
...
"OPTIONS": {
"context_processors": [
...
"django.template.context_processors.request",
...
]
}
}
]
... wtedy obiekt będzie request
dostępny w szablonach i będzie zawierał odniesienie do aktualnego Site
żądania jako request.site
. Następnie możesz pobrać domenę w szablonie za pomocą:
{{request.site.domain}}
A co z tym podejściem? Pracuje dla mnie. Jest również używany w rejestracji 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
przyniesie ci https
schemat (jest uważany za bezpieczny), który nie zadziała, jeśli masz statyczny adres URL (tylko http://127.0.0.1
jest prawidłowy, nie https://127.0.0.1
). Więc nie jest idealny, gdy jest jeszcze w fazie rozwoju.
from django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
Możesz użyć {{ protocol }}://{{ domain }}
w swoich szablonach, aby uzyskać nazwę domeny.
request.META['HTTP_HOST']
daje Ci domenę. W szablonie byłoby to{{ request.META.HTTP_HOST }}
.