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_IDconfiguração é igual ao idatributo do site atual no aplicativo Sites (você pode encontrar idno painel de administração de Sites). Quando você chama get_current, o Django pega o seu SITE_IDe retorna o Siteobjeto 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_HOSTcabeç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 SimpleLazyObjectwrapper garante que a chamada ao banco de dados ocorra apenas quando o modelo realmente usa o siteobjeto. 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)),
}
SimpleLazyObjectaqui, porque o lambda não será chamado se nada acessar o 'site' de qualquer maneira.
SimpleLazyObject, cada RequestContextum 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.
SimpleLazyObjectque há para evitar a reavaliação da função, que não é realmente necessário uma vez que o Siteobjeto é 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_uriestá 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.schemefoi adicionado no Django 1.7.
{{ request.get_host }}deve proteger contra ataques de cabeçalho do host HTTP quando usado junto com a ALLOWED_HOSTSconfiguraçã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
Hostcabeçalho (ouX-Forwarded-HostseUSE_X_FORWARDED_HOSTestiver 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.METAvocê, está ignorando essa proteção de segurança.
Quanto ao uso do requestem 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 RequestContextdiretamente.
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 httpou httpsdependendo 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 httpsconexã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_URLmanteria um valor como example.com
SITE_PROTOCOLmanteria um valor como http ou https
SITE_PROTOCOL_URLmanteria um valor como http://example.comou https://example.com
SITE_PROTOCOL_RELATIVE_URLmanteria 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 requestobjeto disponível nos modelos e ele conterá uma referência à corrente Sitepara 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)
localhostisso fornecerá um httpsesquema (é considerado seguro) que não funcionará se você tiver um URL estático (apenas http://127.0.0.1vá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 }}.