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

How can I get the full/absolute URL (with domain) in Django?

如何在没有Sites模块的情况下获取Django中的完整/绝对URL(例如https://example.com/some/path)? 那真是太傻了......我不应该查询我的数据库以获取URL!

我想用reverse()来使用它。


根据请求使用方便的request.build_absolute_uri()方法,将相关网址传递给它,它会给你一个完整的。

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


如果要将其与reverse()一起使用,可以执行以下操作:request.build_absolute_uri(reverse('view_name', args=(obj.pk, )))


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

例如

1
2
3
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_current_site(request)。您可以使用本机站点框架和get_absolute_url的组合。在管理员中设置至少一个站点,确保您的模型具有get_absolute_url()方法,然后:

1
2
3
4
5
6
7
8
>>> 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


如果您不想访问数据库,可以使用设置进行操作。然后,使用上下文处理器将其添加到每个模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 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

如果您尝试在Django模板中执行此操作,我发布了一个小的PyPI包django-fullurl,让您用fullurlfullstatic替换urlstatic模板标签,如下所示:

1
2
3
4
5
{% load fullurl %}

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

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

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

PyPI > <img src= >
</p>
<p>
在视图中,您当然可以使用<wyn>request.build_absolute_uri</wyn>。
</p>
<div class=


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

view.py

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

您-template.html

1
{{ baseurl }}


在您看来,只需这样做:

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

要从模板创建指向其他页面的完整链接,您可以使用以下命令:

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

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


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


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

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

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

我喜欢的另一个因为你可以轻松地将域,协议和路径放在一起是:

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

这个库允许您简单地在模板中写下您想要的内容,例如:

1
{{url_parts.domain}}


请尝试以下代码:

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


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

1
2
3
4
5
6
7
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框架中提及可用性


这在我的模板中对我有用:

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

我需要完整的url将它传递给js fetch函数。
我希望这对你有帮助。


我知道了:

1
wsgiref.util.request_uri(request.META)

使用模式,主机,端口路径和查询获取完整的uri。


还有ABSOLUTE_URL_OVERRIDES可用作设置

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

但是这会覆盖get_absolute_url(),这可能并不可取。

而不是仅为此安装站点框架或执行此处提到的依赖于请求对象的其他一些内容,我认为更好的解决方案是将其放在models.py中

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

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

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


request.get_host()会为您提供域名。


您还可以使用:

1
2
import socket
socket.gethostname()

这对我来说很好,

我不完全确定它是如何工作的。我相信这是一个更低级别,并将返回您的服务器主机名,这可能与您的用户用于访问您的页面的主机名不同。


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