¿Cómo obtengo el nombre de dominio de mi sitio actual desde una plantilla de Django? He intentado buscar en la etiqueta y los filtros, pero no hay nada allí.
¿Cómo obtengo el nombre de dominio de mi sitio actual desde una plantilla de Django? He intentado buscar en la etiqueta y los filtros, pero no hay nada allí.
Respuestas:
Creo que lo que quiere es tener acceso al contexto de solicitud, consulte RequestContext.
Host:
encabezado y obtiene una respuesta con el dominio falsificado en algún lugar de una página, ¿cómo crea eso un agujero de seguridad? No veo cómo eso difiere de que un usuario tome el HTML generado y se modifique antes de alimentarlo a su propio navegador.
Si desea el encabezado del host HTTP real, vea el comentario de Daniel Roseman sobre la respuesta de @ Phsiao. La otra alternativa es que si está utilizando el marco contrib.sites , puede establecer un nombre de dominio canónico para un Sitio en la base de datos (asignar el dominio de solicitud a un archivo de configuración con el SITE_ID adecuado es algo que debe hacer usted mismo a través de su configuración del servidor web). En ese caso estás buscando:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
tendría que poner el objeto current_site en un contexto de plantilla usted mismo si desea usarlo. Si lo está utilizando por todas partes, puede empaquetarlo en un procesador de contexto de plantilla.
SITE_ID
configuración sea igual al id
atributo del sitio actual en la aplicación Sitios (puede encontrarlo id
en el panel de administración de Sitios). Cuando llamas get_current
, Django toma tu SITE_ID
y devuelve el Site
objeto con esa identificación de la base de datos.
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
He descubierto el {{ request.get_host }}
método.
HTTP_X_FORWARDED_HOST
encabezado HTTP.
request.build_absolute_uri
( docs.djangoproject.com/en/dev/ref/request-response/… )
Complementando a Carl Meyer, puede hacer un procesador de contexto como este:
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",
....
)
puede escribir su propia rutina si desea manejar subdominios o SSL en el procesador de contexto.
La variación del procesador de contexto que uso es:
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)),
}
El SimpleLazyObject
contenedor se asegura de que la llamada a la base de datos solo ocurra cuando la plantilla realmente use el site
objeto. Esto elimina la consulta de las páginas de administración. También almacena en caché el resultado.
e inclúyelo en la configuración:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
En la plantilla, puede usar {{ site.domain }}
para obtener el nombre de dominio actual.
editar: para admitir el cambio de protocolo también, use:
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
aquí, porque de todos modos no se llamará a lambda si nada accede al "sitio".
SimpleLazyObject
, cada RequestContext
llamará get_current_site()
y, por lo tanto, ejecutará una consulta SQL. El contenedor se asegura de que la variable solo se evalúe cuando realmente se usa en la plantilla.
SimpleLazyObject
está ahí para evitar la re-evaluación de la función, que no es realmente necesario ya que el Site
se almacena en caché de objetos.
from django.contrib.sites.shortcuts import get_current_site
Sé que esta pregunta es antigua, pero me topé con ella buscando una forma pitónica para obtener el dominio actual.
def myview(request):
domain = request.build_absolute_uri('/')[:-1]
# that will build the complete domain: http://foobar.com
build_absolute_uri
está documentado aquí .
Rápido y simple, pero no es bueno para la producción:
(en una vista)
request.scheme # http or https
request.META['HTTP_HOST'] # example.com
request.path # /some/content/1/
(en una plantilla)
{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}
Asegúrese de utilizar RequestContext , que es el caso si está utilizando render .
No confíes request.META['HTTP_HOST']
en la producción: esa información proviene del navegador. En cambio, use la respuesta de @ CarlMeyer
request.scheme
. Quizás solo esté disponible en versiones más recientes de django.
request.scheme
se agregó en Django 1.7.
{{ request.get_host }}
debería proteger contra ataques de encabezado de host HTTP cuando se usa junto con la ALLOWED_HOSTS
configuración (agregado en Django 1.4.4).
Tenga en cuenta que {{ request.META.HTTP_HOST }}
no tiene la misma protección. Ver los documentos :
ALLOWED_HOSTS
Una lista de cadenas que representan los nombres de host / dominio que este sitio de Django puede servir. Esta es una medida de seguridad para evitar ataques de encabezado de host HTTP , que son posibles incluso bajo muchas configuraciones de servidor web aparentemente seguras.
... Si el
Host
encabezado (oX-Forwarded-Host
siUSE_X_FORWARDED_HOST
está habilitado) no coincide con ningún valor en esta lista, eldjango.http.HttpRequest.get_host()
método aumentaráSuspiciousOperation
.... Esta validación solo se aplica a través de
get_host()
; si su código accede al encabezado del Host directamente desderequest.META
usted, está pasando por alto esta protección de seguridad.
En cuanto al uso de request
en su plantilla, las llamadas a la función de representación de plantilla han cambiado en Django 1.8 , por lo que ya no tiene que manejar RequestContext
directamente.
Aquí se explica cómo representar una plantilla para una vista, utilizando la función de acceso directo render()
:
from django.shortcuts import render
def my_view(request):
...
return render(request, 'my_template.html', context)
A continuación, le mostramos cómo representar una plantilla para un correo electrónico, cuyo IMO es el caso más común en el que desea el valor de host:
from django.template.loader import render_to_string
def my_view(request):
...
email_body = render_to_string(
'my_template.txt', context, request=request)
Aquí hay un ejemplo de cómo agregar una URL completa en una plantilla de correo electrónico; request.scheme debería obtener http
o, https
según lo que esté usando:
Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
Yo uso una etiqueta de plantilla personalizada. Agregar a, por ejemplo <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
Úselo en una plantilla como esta:
{% load site %}
{% current_domain %}
get_current
es un método documentado: docs.djangoproject.com/en/dev/ref/contrib/sites/…
'http://%s'
podría ser un problema en caso de https
conexión; El esquema no es dinámico en este caso.
Similar a la respuesta del usuario panchicore, esto es lo que hice en un sitio web muy simple. Proporciona algunas variables y las pone a disposición en la plantilla.
SITE_URL
mantendría un valor como example.com
SITE_PROTOCOL
mantendría un valor como http
o https
SITE_PROTOCOL_URL
mantendría un valor como http://example.com
o https://example.com
SITE_PROTOCOL_RELATIVE_URL
mantendría un valor como//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'
Luego, en sus plantillas, los utilizan como {{ SITE_URL }}
, {{ SITE_PROTOCOL }}
, {{ SITE_PROTOCOL_URL }}
y{{ SITE_PROTOCOL_RELATIVE_URL }}
En una plantilla de Django puedes hacer:
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
django.template.context_processors.request
también [este tutorial ayudó] ( simpleisbetterthancomplex.com/tips/2016/07/20/… )
Si utiliza el procesador de contexto de "solicitud" , y está utilizando el marco de sitios de Django , y tiene instalado el middleware del sitio (es decir, su configuración incluye estos):
INSTALLED_APPS = [
...
"django.contrib.sites",
...
]
MIDDLEWARE = [
...
"django.contrib.sites.middleware.CurrentSiteMiddleware",
...
]
TEMPLATES = [
{
...
"OPTIONS": {
"context_processors": [
...
"django.template.context_processors.request",
...
]
}
}
]
... entonces tendrá el request
objeto disponible en plantillas, y contendrá una referencia a la actual Site
para la solicitud como request.site
. Luego puede recuperar el dominio en una plantilla con:
{{request.site.domain}}
¿Qué hay de este enfoque? Funciona para mi. También se usa en el registro de 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
dará un https
esquema (se considera seguro) que no funcionará si tienes una URL estática (solo http://127.0.0.1
es válida, no https://127.0.0.1
). Por lo tanto, no es ideal cuando todavía está en desarrollo.
from django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
Puede usar {{ protocol }}://{{ domain }}
en sus plantillas para obtener su nombre de dominio.
request.META['HTTP_HOST']
te da el dominio En una plantilla sería{{ request.META.HTTP_HOST }}
.