Como posso obter a URL completa / absoluta (por exemplo https://example.com/some/path
) no Django sem o módulo Sites ? Isso é bobagem ... Eu não deveria precisar consultar meu banco de dados para pegar o URL!
Eu quero usá-lo com reverse()
.
Como posso obter a URL completa / absoluta (por exemplo https://example.com/some/path
) no Django sem o módulo Sites ? Isso é bobagem ... Eu não deveria precisar consultar meu banco de dados para pegar o URL!
Eu quero usá-lo com reverse()
.
Respostas:
Use o método request.build_absolute_uri () , a pedido, transmita o URL relativo e ele fornecerá um completo.
Por padrão, a URL absoluta para request.get_full_path()
é retornada, mas você pode passar uma URL relativa como o primeiro argumento para convertê-la em uma URL absoluta.
{{ request.build_absolute_uri }}{{ object.get_absolute_url }}
- e heyho, URL completo.
{% if request.is_secure %}https://{% else %}http://{% endif %}{{ request.get_host }}{{ object.get_absolute_url }}
porque {{ request.build_absolute_uri }}
tinha uma barra à direita e {{ object.get_absolute_url }}
comecei com uma barra, resultando em barras duplas no URL.
Se você quiser usá- reverse()
lo, faça o seguinte:request.build_absolute_uri(reverse('view_name', args=(obj.pk, )))
url_name
vez de view_name
) #
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)
Você também pode usar get_current_site
como parte do aplicativo de sites ( from django.contrib.sites.models import get_current_site
). Ele pega um objeto de solicitação e o padrão é o objeto de site com o qual você configurou SITE_ID
em settings.py, se solicitado None
. Leia mais na documentação para usar a estrutura de sites
por exemplo
from django.contrib.sites.shortcuts import get_current_site
request = None
full_url = ''.join(['http://', get_current_site(request).domain, obj.get_absolute_url()])
Não é tão compacto / elegante quanto request.build_absolute_url()
, mas é utilizável quando os objetos de solicitação não estão disponíveis e você tem um URL de site padrão.
django.contrib.sites
na sua INSTALLED_APPS
, não vai bater o DB em tudo, e fornecer informações com base no objeto Request (veja get_current_site )
build_absolute_uri
ainda parece a solução mais fácil e limpa.
Se você não conseguir acessar request
, não poderá usá-lo get_current_site(request)
conforme recomendado em algumas soluções aqui. Você pode usar uma combinação da estrutura nativa de Sites get_absolute_url
. Configure pelo menos um site no administrador, verifique se o seu modelo possui um método get_absolute_url () e , em seguida:
>>> from django.contrib.sites.models import Site
>>> domain = Site.objects.get_current().domain
>>> obj = MyModel.objects.get(id=3)
>>> path = obj.get_absolute_url()
>>> url = 'http://{domain}{path}'.format(domain=domain, path=path)
>>> print(url)
'http://example.com/mymodel/objects/3/'
https://docs.djangoproject.com/en/dev/ref/contrib/sites/#getting-the-current-domain-for-full-urls
request
a None
ou chamada get_current_site(None)
.
Se você não quiser acessar o banco de dados, poderá fazê-lo com uma configuração. Em seguida, use um processador de contexto para adicioná-lo a todos os modelos:
# settings.py (Django < 1.9)
...
BASE_URL = 'http://example.com'
TEMPLATE_CONTEXT_PROCESSORS = (
...
'myapp.context_processors.extra_context',
)
# settings.py (Django >= 1.9)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
# Additional
'myapp.context_processors.extra_context',
],
},
},
]
# myapp/context_processors.py
from django.conf import settings
def extra_context(request):
return {'base_url': settings.BASE_URL}
# my_template.html
<p>Base url is {{ base_url }}.</p>
django-fullurl
Se você está tentando fazer isso em um modelo do Django, lançamos um pequeno pacote PyPI django-fullurl
para permitir a substituição url
e as static
tags de modelos por fullurl
e fullstatic
, assim:
{% load fullurl %}
Absolute URL is: {% fullurl "foo:bar" %}
Another absolute URL is: {% fullstatic "kitten.jpg" %}
Espera-se que esses emblemas se mantenham atualizados automaticamente:
Em uma exibição, é claro que você pode usar request.build_absolute_uri
.
request
objeto para obter o nome de domínio. Nesse caso, você deve usar a sites
estrutura, que obtém o nome de domínio do banco de dados. Consulte django-absoluteuri
, mencionado na seção "consulte também" do README deste pacote PyPI.
Para criar um link completo para outra página a partir de um modelo, você pode usar este:
{{ request.META.HTTP_HOST }}{% url 'views.my_view' my_arg %}
request.META.HTTP_HOST fornece o nome do host e url fornece o nome relativo. O mecanismo do modelo concatena-os em um URL completo.
http
neste contexto) e ://
parte do URL, portanto, ele não fornecerá um URL completo .
Mais uma maneira. Você pode usar build_absolute_uri()
no seu view.py
e passá-lo para o modelo.
view.py
def index(request):
baseurl = request.build_absolute_uri()
return render_to_response('your-template.html', { 'baseurl': baseurl })
your-template.html
{{ baseurl }}
HttpRequest.build_absolute_uri(request)
é equivalente a request.build_absolute_uri()
não é?
Examine o Request.META
dicionário que entra. Acho que tem nome e porta do servidor.
Isso funcionou para mim no meu modelo:
{{ request.scheme }}:{{ request.META.HTTP_HOST }}{% url 'equipos:marca_filter' %}
Eu precisava do URL completo para passá-lo para uma função js fetch. Espero que isso lhe ajude.
Eu sei que esta é uma pergunta antiga. Mas acho que as pessoas ainda se deparam muito com isso.
Existem algumas bibliotecas por aí que complementam a funcionalidade padrão do Django. Eu tentei alguns. Gosto da seguinte biblioteca ao fazer referência inversa a URLs absolutos:
https://github.com/fusionbox/django-absoluteuri
Outro que eu gosto, porque você pode facilmente montar um domínio, protocolo e caminho é:
https://github.com/RRMoelker/django-full-url
Esta biblioteca permite que você simplesmente escreva o que deseja em seu modelo, por exemplo:
{{url_parts.domain}}
Se você estiver usando a estrutura REST do django, poderá usar a função reversa de rest_framework.reverse
. Isso tem o mesmo comportamento que django.core.urlresolvers.reverse
, exceto que ele usa um parâmetro de solicitação para criar um URL completo.
from rest_framework.reverse import reverse
# returns the full url
url = reverse('view_name', args=(obj.pk,), request=request)
# returns only the relative url
url = reverse('view_name', args=(obj.pk,))
Editado para mencionar disponibilidade apenas na estrutura REST
request=request
. Ele também não parece ser pedido está documentado aqui docs.djangoproject.com/en/1.9/ref/urlresolvers/#reverse
Também há ABSOLUTE_URL_OVERRIDES disponível como uma configuração
https://docs.djangoproject.com/en/2.1/ref/settings/#absolute-url-overrides
Mas isso substitui get_absolute_url (), o que pode não ser desejável.
Em vez de instalar a estrutura de sites apenas para isso ou fazer algumas das outras coisas mencionadas aqui que dependem do objeto de solicitação, acho que a melhor solução é colocá-lo no models.py
Defina BASE_URL em settings.py, depois importe-o para models.py e crie uma classe abstrata (ou adicione-a a uma que você já esteja usando) que define get_truly_absolute_url (). Pode ser tão simples quanto:
def get_truly_absolute_url(self):
return BASE_URL + self.get_absolute_url()
Subclasse e agora você pode usá-lo em qualquer lugar.
Conforme mencionado em outras respostas, request.build_absolute_uri()
é perfeito se você tiver acesso request
esites
estrutura é excelente, desde que URLs diferentes apontem para bancos de dados diferentes.
No entanto, meu caso de uso foi um pouco diferente. Meu servidor intermediário e o servidor de produção acessam o mesmo banco de dados, mas get_current_site
ambos retornaram o primeiro site
no banco de dados. Para resolver isso, você precisa usar algum tipo de variável de ambiente. Você pode usar 1) uma variável de ambiente (algo como os.environ.get('SITE_URL', 'localhost:8000')
) ou 2) SITE_ID
s diferentes para servidores diferentes E settings.py diferentes .
Espero que alguém ache isso útil!
Me deparei com esse segmento porque estava procurando criar um URI absoluto para uma página de sucesso. request.build_absolute_uri()
me deu um URI para minha visão atual, mas para obter a URI para minha visão de sucesso, usei o seguinte ....
request.build_absolute_uri (reverse ('success_view_name'))
Você também pode usar:
import socket
socket.gethostname()
Isso está funcionando bem para mim,
Não tenho muita certeza de como isso funciona. Acredito que este seja um nível um pouco mais baixo e retornará o nome do host do servidor, que pode ser diferente do nome do host usado pelo usuário para acessar sua página.