Como obtenho o nome de domínio do meu site atual de um modelo do Django? Eu tentei procurar na tag e nos filtros, mas nada lá.
Como obtenho o nome de domínio do meu site atual de um modelo do Django? Eu tentei procurar na tag e nos filtros, mas nada lá.
Respostas:
Eu acho que o que você quer é ter acesso ao contexto da solicitação, consulte RequestContext.
Host:
cabeçalho e recebe uma resposta de volta com o domínio falsificado em algum lugar da página, como isso cria uma brecha na segurança? Não vejo como isso difere de um usuário pegar o HTML gerado e se modificar antes de alimentá-lo em seu próprio navegador.
Se você deseja o cabeçalho HTTP Host real, consulte o comentário de Daniel Roseman na resposta de @ Phsiao. A outra alternativa é que, se você estiver usando a estrutura contrib.sites , poderá definir um nome de domínio canônico para um Site no banco de dados (mapear o domínio de solicitação para um arquivo de configurações com o SITE_ID adequado é algo que você deve fazer através do seu configuração do servidor da web). Nesse caso, você está procurando:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
você teria que colocar o objeto current_site em um contexto de modelo, se quiser usá-lo. Se você estiver usando tudo isso em qualquer lugar, poderá empacotar isso em um processador de contexto de modelo.
SITE_ID
configuração é igual ao id
atributo do site atual no aplicativo Sites (você pode encontrar id
no painel de administração de Sites). Quando você chama get_current
, o Django pega o seu SITE_ID
e retorna o Site
objeto com esse ID do banco de dados.
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
Eu descobri o {{ request.get_host }}
método.
HTTP_X_FORWARDED_HOST
cabeçalho HTTP.
request.build_absolute_uri
( docs.djangoproject.com/en/dev/ref/request-response/... )
Complementando Carl Meyer, você pode criar um processador 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",
....
)
você pode escrever sua própria rotina se desejar manipular subdomínios ou SSL no processador de contexto.
A variação do processador de contexto que eu uso é:
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)),
}
O SimpleLazyObject
wrapper garante que a chamada ao banco de dados ocorra apenas quando o modelo realmente usa o site
objeto. Isso remove a consulta das páginas de administração. Ele também armazena em cache o resultado.
e inclua-o nas configurações:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
No modelo, você pode usar {{ site.domain }}
para obter o nome de domínio atual.
edit: para suportar também a troca de protocolo, 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
aqui, porque o lambda não será chamado se nada acessar o 'site' de qualquer maneira.
SimpleLazyObject
, cada RequestContext
um chamará get_current_site()
e, portanto, executará uma consulta SQL. O wrapper garante que a variável seja avaliada apenas quando for realmente usada no modelo.
SimpleLazyObject
que há para evitar a reavaliação da função, que não é realmente necessário uma vez que o Site
objeto é armazenado em cache.
from django.contrib.sites.shortcuts import get_current_site
Sei que essa pergunta é antiga, mas me deparei com ela procurando uma maneira pitônica de obter o domínio atual.
def myview(request):
domain = request.build_absolute_uri('/')[:-1]
# that will build the complete domain: http://foobar.com
build_absolute_uri
está documentado aqui .
Rápido e simples, mas não bom para produção:
(em uma exibição)
request.scheme # http or https
request.META['HTTP_HOST'] # example.com
request.path # /some/content/1/
(em um modelo)
{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}
Certifique-se de usar um RequestContext , que é o caso se você estiver usando renderização .
Não confie request.META['HTTP_HOST']
na produção: essas informações vêm do navegador. Em vez disso, use a resposta do @ CarlMeyer
request.scheme
. Talvez apenas disponível em versões mais recentes do django.
request.scheme
foi adicionado no Django 1.7.
{{ request.get_host }}
deve proteger contra ataques de cabeçalho do host HTTP quando usado junto com a ALLOWED_HOSTS
configuração (adicionada no Django 1.4.4).
Observe que {{ request.META.HTTP_HOST }}
não possui a mesma proteção. Veja os documentos :
ALLOWED_HOSTS
Uma lista de strings representando os nomes de host / domínio que este site do Django pode servir. Essa é uma medida de segurança para impedir ataques ao cabeçalho do host HTTP , que são possíveis mesmo em muitas configurações de servidor da Web aparentemente seguras.
... Se o
Host
cabeçalho (ouX-Forwarded-Host
seUSE_X_FORWARDED_HOST
estiver ativado) não corresponder a nenhum valor nesta lista, odjango.http.HttpRequest.get_host()
método aumentaráSuspiciousOperation
.... Esta validação se aplica apenas a
get_host()
; se o seu código acessar o cabeçalho do host diretamente derequest.META
você, está ignorando essa proteção de segurança.
Quanto ao uso do request
em seu modelo, as chamadas de função de renderização de modelo foram alteradas no Django 1.8 , assim você não precisa mais lidar RequestContext
diretamente.
Veja como renderizar um modelo para uma visualização, usando a função de atalho render()
:
from django.shortcuts import render
def my_view(request):
...
return render(request, 'my_template.html', context)
Veja como renderizar um modelo para um email, qual IMO é o caso mais comum em que você deseja o valor do host:
from django.template.loader import render_to_string
def my_view(request):
...
email_body = render_to_string(
'my_template.txt', context, request=request)
Aqui está um exemplo de adição de um URL completo em um modelo de email; request.scheme deve obter http
ou https
dependendo do que você está usando:
Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
Eu uso uma tag de modelo personalizado. Adicione, por exemplo <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
Use-o em um modelo como este:
{% load site %}
{% current_domain %}
get_current
é um método documentado: docs.djangoproject.com/en/dev/ref/contrib/sites/…
'http://%s'
pode ser um problema em caso de https
conexão; esquema não é dinâmico neste caso.
Semelhante à resposta do usuário panchicore, foi o que fiz em um site muito simples. Ele fornece algumas variáveis e as disponibiliza no modelo.
SITE_URL
manteria um valor como example.com
SITE_PROTOCOL
manteria um valor como http
ou https
SITE_PROTOCOL_URL
manteria um valor como http://example.com
ou https://example.com
SITE_PROTOCOL_RELATIVE_URL
manteria um 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'
Então, em seus modelos, usá-los como {{ SITE_URL }}
, {{ SITE_PROTOCOL }}
, {{ SITE_PROTOCOL_URL }}
e{{ SITE_PROTOCOL_RELATIVE_URL }}
Em um modelo do Django, você pode fazer:
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
django.template.context_processors.request
, também [este how-to ajudou] ( simpleisbetterthancomplex.com/tips/2016/07/20/... )
Se você usa o processador de contexto "request" e está usando a estrutura de sites do Django e possui o middleware Site instalado (ou seja, suas configurações incluem estas):
INSTALLED_APPS = [
...
"django.contrib.sites",
...
]
MIDDLEWARE = [
...
"django.contrib.sites.middleware.CurrentSiteMiddleware",
...
]
TEMPLATES = [
{
...
"OPTIONS": {
"context_processors": [
...
"django.template.context_processors.request",
...
]
}
}
]
... então você terá o request
objeto disponível nos modelos e ele conterá uma referência à corrente Site
para a solicitação como request.site
. Você pode recuperar o domínio em um modelo com:
{{request.site.domain}}
E essa abordagem? Funciona para mim. Também é usado no django-registration .
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
isso fornecerá um https
esquema (é considerado seguro) que não funcionará se você tiver um URL estático (apenas http://127.0.0.1
válido, não https://127.0.0.1
). Portanto, não é o ideal quando ainda está em desenvolvimento.
from django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
Você pode usar {{ protocol }}://{{ domain }}
em seus modelos para obter seu nome de domínio.
request.META['HTTP_HOST']
fornece o domínio. Em um modelo seria{{ request.META.HTTP_HOST }}
.