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

时间:2010-02-27 00:29:00

标签: django

如何在Django without the Sites module中获取完整/绝对网址(例如https://example.com/some/path)?那真是太傻了......我不应该查询我的数据库以获取URL!

我想将其与reverse()一起使用。

25 个答案:

答案 0 :(得分:470)

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

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

答案 1 :(得分:77)

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

答案 2 :(得分:53)

您还可以将get_current_site用作网站应用(from django.contrib.sites.models import get_current_site)的一部分。它需要一个请求对象,如果请求为SITE_ID,则默认为您在settings.py中使用None配置的站点对象。阅读using the sites framework

的文档中的更多内容

e.g。

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。

答案 3 :(得分:44)

如果您无法访问request,则无法按照此处某些解决方案中的建议使用get_current_site(request)。您可以使用本机站点框架和get_absolute_url的组合。在管理员中设置至少一个Site,确保您的模型采用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

答案 4 :(得分:16)

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

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

答案 5 :(得分:12)

django-fullurl

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

{% load fullurl %}

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

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

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

PyPI Travis CI

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

答案 6 :(得分:8)

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

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

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

答案 7 :(得分:8)

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

<强> view.py

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

您-template.html

{{ baseurl }}

答案 8 :(得分:7)

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

答案 9 :(得分:7)

在您看来,只需这样做:

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

答案 10 :(得分:5)

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

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

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

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

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

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

{{url_parts.domain}}

答案 11 :(得分:5)

请尝试以下代码:

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

答案 12 :(得分:4)

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

这是我的代码:

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/

答案 13 :(得分:3)

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

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

我需要完整的URL才能将其传递给js fetch函数。 希望对您有帮助。

答案 14 :(得分:2)

如果您正在使用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框架中提及可用性

答案 15 :(得分:1)

我明白了:

wsgiref.util.request_uri(request.META)

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

答案 16 :(得分:0)

还有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()的抽象类(或将其添加到您正在使用的类中)。可能很简单:

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

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

答案 17 :(得分:0)

如其他答案中所述,如果您可以访问request.build_absolute_uri()request是完美的选择,并且只要不同的URL指向不同的数据库,sites框架就很好。

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

希望有人会发现它有用!

答案 18 :(得分:0)

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

request.build_absolute_uri(reverse('success_view_name'))

答案 19 :(得分:0)

您可以传递请求reverse('view-name', request=request)或在build_absolute_uri request.build_absolute_uri(reverse('view-name'))内包含reverse()

答案 20 :(得分:0)

<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

答案 21 :(得分:-1)

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]

答案 22 :(得分:-2)

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

答案 23 :(得分:-4)

您也可以使用:

-i

这对我来说很好,

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

答案 24 :(得分:-4)

您可以尝试&#34; request.get_full_path()&#34;