如何在Django中获得完整/绝对的URL(带域)?

如何在Django 没有Sites模块中获得完整/绝对的URL(例如https://example.com/some/path) ?这太愚蠢了……我不需要查询我的数据库来抓取URL!

我想与reverse()一起使用它。

402073 次浏览

检查输入的Request.META字典。我认为它有服务器名和服务器端口。

在请求时使用方便的request.build_absolute_uri ()方法,将相对url传递给它,它会给你一个完整的url。

默认情况下,返回request.get_full_path()的绝对URL,但您可以将相对URL作为第一个参数传递给它,以将其转换为绝对URL。

>>> request.build_absolute_uri()
'https://example.com/music/bands/the_beatles/?print=true'
>>> request.build_absolute_uri('/bands/?print=true')
'https://example.com/bands/?print=true'

你也可以使用get_current_site作为站点应用程序(from django.contrib.sites.models import get_current_site)的一部分。它接受一个请求对象,如果request是None,则默认为您在settings.py中使用SITE_ID配置的站点对象。在使用网站框架文档中阅读更多内容

如。

from django.contrib.sites.shortcuts import get_current_site
request = None
full_url = ''.join(['http://', get_current_site(request).domain, obj.get_absolute_url()])

它不像request.build_absolute_url()那样紧凑/整洁,但当请求对象不可用时,并且你有一个默认的站点url时,它是可用的。

你可以试试"request.get_full_path()"

如果你想在reverse()中使用它,你可以这样做:request.build_absolute_uri(reverse('view_name', args=(obj.pk, )))

如果你不能访问request,那么你就不能像这里的一些解决方案中推荐的那样使用get_current_site(request)。你可以使用本地Sites框架和get_absolute_url的组合。在管理中至少设置一个网站,确保你的模型有一个get_absolute_url ()方法,然后:

>>> 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

如果你不想访问数据库,你可以通过设置来实现。然后,使用上下文处理器将其添加到每个模板:

# 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>

要从模板创建到另一个页面的完整链接,您可以使用以下命令:

\{\{ request.META.HTTP_HOST }}{% url 'views.my_view' my_arg %}

request.META。HTTP_HOST给出主机名,url给出相对名。然后模板引擎将它们连接成一个完整的url。

还有另一种方式。你可以在你的view.py中使用build_absolute_uri()并将它传递给模板。

view.py

def index(request):
baseurl = request.build_absolute_uri()
return render_to_response('your-template.html', { 'baseurl': baseurl })

your-template.html

\{\{ baseurl }}

我知道这是一个老问题。但我认为人们仍然经常遇到这种情况。

有几个库可以补充Django的默认功能。我试过一些。当反向引用绝对url时,我喜欢以下库:

https://github.com/fusionbox/django-absoluteuri

另一个我喜欢的是,因为你可以很容易地把域、协议和路径放在一起:

https://github.com/RRMoelker/django-full-url

这个库允许你在模板中简单地写你想要的东西,例如:

\{\{url_parts.domain}}

request.get_host()会给你域名。

你还可以使用:

import socket
socket.gethostname()

这对我来说很好,

我不太清楚它是怎么运作的。我相信这是更低级的,它将返回您的服务器主机名,这可能与您的用户访问您的页面所使用的主机名不同。

我明白了:

wsgiref.util.request_uri(request.META)

获取包含模式、主机、端口路径和查询的完整uri。

如果你正在使用django REST框架,你可以使用rest_framework.reverse的反向函数。它具有与django.core.urlresolvers.reverse相同的行为,除了它使用一个请求参数来构建一个完整的URL。

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,))

经过编辑,只提到REST框架中的可用性

在你看来,只需这样做:

base_url =  "{0}://{1}{2}".format(request.scheme, request.get_host(), request.path)

试试下面的代码:

\{\{ request.scheme }}://\{\{ request.META.HTTP_HOST }}

django-fullurl

如果你想在Django模板中这样做,我已经发布了一个小的PyPI包django-fullurl,让你用fullurlfullstatic替换urlstatic模板标签,就像这样:

{% load fullurl %}


Absolute URL is: {% fullurl "foo:bar" %}


Another absolute URL is: {% fullstatic "kitten.jpg" %}

这些徽章应该自动保持最新:

PyPI Travis CI .

在视图中,你当然可以使用request.build_absolute_uri来代替。

这在我的模板中很管用:

\{\{ request.scheme }}://\{\{ request.META.HTTP_HOST }}{% url 'equipos:marca_filter' %}

我需要完整的url传递给一个js获取函数。 我希望这对你有帮助。

还有ABSOLUTE_URL_OVERRIDES可用作为设置

https://docs.djangoproject.com/en/2.1/ref/settings/#absolute-url-overrides

但这将覆盖get_absolute_url(),这可能是不可取的。

我认为更好的解决方案是把它放在models.py中,而不是仅仅为此安装sites框架,或者做一些这里提到的依赖于request对象的其他事情

在settings.py中定义BASE_URL,然后将其导入models.py并创建一个抽象类(或将其添加到您已经在使用的类中),该类定义get_truly_absolute_url()。它可以很简单:

def get_truly_absolute_url(self):
return BASE_URL + self.get_absolute_url()

子类化它,现在你可以在任何地方使用它。

正如在其他答案中提到的,如果你可以访问requestrequest.build_absolute_uri()是完美的,而sites框架是伟大的,只要不同的url指向不同的数据库。

然而,我的用例略有不同。我的登台服务器和生产服务器访问同一个数据库,但是get_current_site都返回了数据库中的第一个site。要解决这个问题,必须使用某种环境变量。你可以使用1)一个环境变量(类似os.environ.get('SITE_URL', 'localhost:8000'))或2)不同服务器的不同__abc5和不同settings.py

希望有人会觉得这有用!

我遇到这个线程是因为我正在寻找为成功页面构建一个绝对URI。request.build_absolute_uri()给了我当前视图的URI,但为了获得我的成功视图的URI,我使用了以下....

request.build_absolute_uri(反向(success_view_name))

你可以传递request reverse('view-name', request=request)或者用build_absolute_uri request.build_absolute_uri(reverse('view-name'))将reverse()括起来

<div class='col-12 col-md-6'>
<p class='lead'>Login</p>
{% include 'accounts/snippets/form.html' with form=login_form next_url=request.build_absolute_uri %}
</div>

例如,在这里,我说加载表单,并告诉表单,下一个URL是当前的URL,这段代码呈现

如果有人对获取带有参数在模板中的绝对反向url感兴趣,最简洁的方法是通过扩展和使用现有默认代码创建自己的{% url %} 模板标签的绝对版本。

这是我的代码:

from django import template
from django.template.defaulttags import URLNode, url


register = template.Library()


class AbsURLNode(URLNode):
def __init__(self, view_name, args, kwargs, asvar):
super().__init__(view_name, args, kwargs, asvar)


def render(self, context):
url     = super().render(context)
request = context['request']


return request.build_absolute_uri(url)




@register.tag
def abs_url(parser, token):


urlNode = url(parser, token)
return AbsURLNode( urlNode.view_name, urlNode.args, urlNode.kwargs, urlNode.asvar  )

在模板中的使用:

{% load wherever_your_stored_this_tag_file %}
{% abs_url 'view_name' parameter %}

将渲染(示例):

http://example.com/view_name/parameter/

而不是

/view_name/parameter/
class WalletViewSet(mixins.ListModelMixin, GenericViewSet):
serializer_class = WalletSerializers
pagination_class = CustomPaginationInvestment


def get_queryset(self):


######################################################
print(self.request.build_absolute_uri())
#####################################################


wallet, created = Wallet.objects.get_or_create(owner=self.request.user)
return Wallet.objects.filter(id=wallet.id)

你得到这样的输出

http://localhost:8000/v1/wallet
HTTP GET /v1/wallet 200 [0.03, 127.0.0.1:41608]

不是绝对的url,但我正在寻找只是得到主机。如果你想在view.py中获得host,你可以这样做

def my_view(request):
host = f"{ request.scheme }://{ request.META.get('HTTP_HOST') }"

在做一个项目的时候,我学会了在Django中获取完整/绝对的URL。

如果你的URL在地址栏中是这样的:

https://stackoverflow.com/questions/2345708

如果你想把上面的URL显示给你的模板。

  1. \{\{ request.path }} #Without GET parameters.
  2. \{\{ request.get_full_path }} #with GET parameters

对于上面的两个代码,这将打印在你的模板中

questions/2345708

而且另一种获取完整URL的方法是:

  • \{\{request.build_absolute_uri}}

这将打印在你的模板将是:

https://stackoverflow.com/questions/2345708

我使用这个代码:

request.build_absolute_uri('/')[:-1]

回应:

https://yourdomain.com
request.get_host()

在django中使用这个请求对象