Wie erhalte ich den Domainnamen meiner aktuellen Site aus einer Django-Vorlage? Ich habe versucht, in das Tag und die Filter zu schauen, aber nichts dort.
Wie erhalte ich den Domainnamen meiner aktuellen Site aus einer Django-Vorlage? Ich habe versucht, in das Tag und die Filter zu schauen, aber nichts dort.
Antworten:
Ich denke, Sie möchten Zugriff auf den Anforderungskontext haben, siehe RequestContext.
Host:
Header fälscht und irgendwo auf einer Seite eine Antwort mit der gefälschten Domain erhält, wie entsteht dann eine Sicherheitslücke? Ich sehe nicht, wie sich das von einem Benutzer unterscheidet, der den generierten HTML-Code nimmt und sich selbst ändert, bevor er ihn seinem eigenen Browser zuführt.
Wenn Sie den eigentlichen HTTP-Host-Header möchten, lesen Sie Daniel Rosemans Kommentar zur Antwort von @ Phsiao. Die andere Alternative besteht darin, dass Sie bei Verwendung des Contrib.sites-Frameworks einen kanonischen Domänennamen für eine Site in der Datenbank festlegen können (das Zuordnen der Anforderungsdomäne zu einer Einstellungsdatei mit der richtigen SITE_ID müssen Sie selbst über Ihre durchführen Webserver-Setup). In diesem Fall suchen Sie:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
Sie müssten das current_site-Objekt selbst in einen Vorlagenkontext einfügen, wenn Sie es verwenden möchten. Wenn Sie es überall verwenden, können Sie es in einem Vorlagenkontextprozessor verpacken.
SITE_ID
Einstellung dem id
Attribut der aktuellen Site in der Sites-App entspricht (Sie finden sie id
im Sites-Admin-Bereich). Wenn Sie anrufen get_current
, nimmt Django Ihre SITE_ID
und gibt das Site
Objekt mit dieser ID aus der Datenbank zurück.
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
Ich habe die {{ request.get_host }}
Methode entdeckt.
HTTP_X_FORWARDED_HOST
HTTP-Header berücksichtigt wird.
request.build_absolute_uri
( docs.djangoproject.com/de/dev/ref/request-response/… )
Als Ergänzung zu Carl Meyer können Sie einen Kontextprozessor wie folgt erstellen:
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",
....
)
Sie können Ihre eigene Rutine schreiben, wenn Sie Subdomains oder SSL im Kontextprozessor verarbeiten möchten.
Die Variation des von mir verwendeten Kontextprozessors ist:
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)),
}
Der SimpleLazyObject
Wrapper stellt sicher, dass der DB-Aufruf nur dann erfolgt, wenn die Vorlage tatsächlich den verwendetsite
Objekt . Dadurch wird die Abfrage von den Administrationsseiten entfernt. Es speichert auch das Ergebnis zwischen.
und in die Einstellungen aufnehmen:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
In der Vorlage können Sie {{ site.domain }}
den aktuellen Domainnamen abrufen.
Bearbeiten: Um auch die Protokollumschaltung zu unterstützen, verwenden Sie:
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
, da das Lambda nicht aufgerufen wird, wenn ohnehin nichts auf 'site' zugreift.
SimpleLazyObject
, RequestContext
ruft jeder auf get_current_site()
und führt daher eine SQL-Abfrage aus. Der Wrapper stellt sicher, dass die Variable nur ausgewertet wird, wenn sie tatsächlich in der Vorlage verwendet wird.
SimpleLazyObject
ist es Umwertung der Funktion zu vermeiden, die benötigt nicht wirklich, da das Site
Objekt zwischengespeichert wird.
from django.contrib.sites.shortcuts import get_current_site
Ich weiß, dass diese Frage alt ist, aber ich bin darauf gestoßen und habe nach einem pythonischen Weg gesucht, um die aktuelle Domain zu erhalten.
def myview(request):
domain = request.build_absolute_uri('/')[:-1]
# that will build the complete domain: http://foobar.com
build_absolute_uri
ist hier dokumentiert .
Schnell und einfach, aber nicht gut für die Produktion:
(in einer Ansicht)
request.scheme # http or https
request.META['HTTP_HOST'] # example.com
request.path # /some/content/1/
(in einer Vorlage)
{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}
Stellen Sie sicher, dass Sie einen RequestContext verwenden. Dies ist der Fall, wenn Sie Render verwenden .
Vertrauen Sie nicht request.META['HTTP_HOST']
auf die Produktion: Diese Informationen stammen aus dem Browser. Verwenden Sie stattdessen die Antwort von @ CarlMeyer
request.scheme
. Möglicherweise nur in neueren Versionen von Django verfügbar.
request.scheme
wurde in Django 1.7 hinzugefügt.
{{ request.get_host }}
sollte vor HTTP-Host-Header-Angriffen schützen, wenn sie zusammen mit dem verwendet werden ALLOWED_HOSTS
Einstellung verwendet werden (hinzugefügt in Django 1.4.4).
Beachten Sie, dass {{ request.META.HTTP_HOST }}
dies nicht den gleichen Schutz bietet. Siehe die Dokumente :
ALLOWED_HOSTS
Eine Liste von Zeichenfolgen, die die Host- / Domänennamen darstellen, die diese Django-Site bedienen kann. Dies ist eine Sicherheitsmaßnahme, um HTTP-Host-Header-Angriffe zu verhindern , die selbst unter vielen scheinbar sicheren Webserverkonfigurationen möglich sind.
... Wenn der
Host
Header (oderX-Forwarded-Host
wenn erUSE_X_FORWARDED_HOST
aktiviert ist) keinem Wert in dieser Liste entspricht, wird diedjango.http.HttpRequest.get_host()
Methode ausgelöstSuspiciousOperation
.... Diese Validierung gilt nur über
get_host()
; Wenn Ihr Code direkt vonrequest.META
Ihnen auf den Host-Header zugreift , wird dieser Sicherheitsschutz umgangen.
In Django 1.8request
haben sich die Funktionsaufrufe für das Rendern von Vorlagen in Ihrer Vorlage geändert , sodass Sie sie nicht mehr verarbeiten müssenRequestContext
direkt .
So rendern Sie eine Vorlage für eine Ansicht mithilfe der Verknüpfungsfunktion render()
:
from django.shortcuts import render
def my_view(request):
...
return render(request, 'my_template.html', context)
So rendern Sie eine Vorlage für eine E-Mail. IMO ist der häufigste Fall, in dem Sie den Hostwert möchten:
from django.template.loader import render_to_string
def my_view(request):
...
email_body = render_to_string(
'my_template.txt', context, request=request)
Hier ist ein Beispiel für das Hinzufügen einer vollständigen URL zu einer E-Mail-Vorlage. request.scheme sollte erhalten http
oder https
abhängig davon, was Sie verwenden:
Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
Ich verwende ein benutzerdefiniertes Vorlagen-Tag. Hinzufügen zu zB <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
Verwenden Sie es in einer Vorlage wie dieser:
{% load site %}
{% current_domain %}
get_current
ist eine dokumentierte Methode: docs.djangoproject.com/de/dev/ref/contrib/sites/…
'http://%s'
könnte im Falle einer https
Verbindung ein Problem sein ; Schema ist in diesem Fall nicht dynamisch.
Ähnlich wie bei der Antwort von Benutzer panchicore habe ich dies auf einer sehr einfachen Website getan. Es enthält einige Variablen und stellt sie in der Vorlage zur Verfügung.
SITE_URL
würde einen Wert wie example.com
SITE_PROTOCOL
halten würde einen Wert wie halten http
oder https
SITE_PROTOCOL_URL
würde einen Wert wie halten http://example.com
oder https://example.com
SITE_PROTOCOL_RELATIVE_URL
würde einen Wert wie halten //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'
Dann auf die Vorlagen, nutzen sie als {{ SITE_URL }}
, {{ SITE_PROTOCOL }}
, {{ SITE_PROTOCOL_URL }}
und{{ SITE_PROTOCOL_RELATIVE_URL }}
In einer Django-Vorlage können Sie Folgendes tun:
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
django.template.context_processors.request
, auch [diese Anleitung half] ( simpleisbetterthancomplex.com/tips/2016/07/20/… )
Wenn Sie den Kontextprozessor "request" verwenden und das Django-Sites-Framework verwenden und die Site-Middleware installiert haben (dh Ihre Einstellungen umfassen diese):
INSTALLED_APPS = [
...
"django.contrib.sites",
...
]
MIDDLEWARE = [
...
"django.contrib.sites.middleware.CurrentSiteMiddleware",
...
]
TEMPLATES = [
{
...
"OPTIONS": {
"context_processors": [
...
"django.template.context_processors.request",
...
]
}
}
]
... dann haben Sie das request
Objekt in Vorlagen zur Verfügung und es enthält einen Verweis auf den aktuellen Site
für die Anfrage als request.site
. Sie können die Domain dann in einer Vorlage abrufen mit:
{{request.site.domain}}
Was ist mit diesem Ansatz? Funktioniert bei mir. Es wird auch bei der Django-Registrierung verwendet .
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
erhalten Sie ein https
Schema (es wird als sicher angesehen), das nicht funktioniert, wenn Sie eine statische URL haben (nur http://127.0.0.1
gültig, nicht gültig https://127.0.0.1
). Es ist also nicht ideal, wenn es sich noch in der Entwicklung befindet.
from django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
Sie können {{ protocol }}://{{ domain }}
in Ihren Vorlagen verwenden, um Ihren Domain-Namen zu erhalten.
request.META['HTTP_HOST']
gibt Ihnen die Domain. In einer Vorlage wäre es{{ request.META.HTTP_HOST }}
.