How can I get the full/absolute URL (with domain) in Django?
如何在没有Sites模块的情况下获取Django中的完整/绝对URL(例如https://example.com/some/path)? 那真是太傻了......我不应该查询我的数据库以获取URL!
我想用reverse()来使用它。
-
旁白:站点模块只在第一次需要站点名称时才会访问数据库,结果缓存在模块变量(SITE_CACHE)中,该变量将一直存在,直到重新编译模块或SiteManager.clear_cache() 方法被调用。 请参阅:code.djangoproject.com/svn/django/tags/releases/1.3/django/
根据请求使用方便的request.build_absolute_uri()方法,将相关网址传递给它,它会给你一个完整的。
默认情况下,返回request.get_full_path()的绝对URL,但您可以将相对URL作为第一个参数传递给它,以将其转换为绝对URL。
-
+1此函数使用我的答案中的相同数据。绝对是一个更方便的选择。
-
url怎么样:localhost / home /#/ test?我只能看到localhost / home。如何在锐利之后看到这个部分?
-
#之后的所有内容都没有传递给服务器,它只是浏览器功能
-
在模板中(你不能给出参数)你可以这样做:{{ request.build_absolute_uri }}{{ object.get_absolute_url }} - 和heyho,完整网址。
-
这对于django中大多数可以获得请求对象的地方来说都是一个很好的答案,但Darb的回答stackoverflow.com/questions/2345708/非常适用于信号处理等应用程序,以便在电子邮件中生成链接等。当你没有一个请求对象方便。
-
如果我无法访问请求怎么办?就像在Django-REST-Framework的Serializers中一样?
-
IIRC你可以从序列化器self.context请求,或者至少你可以把它放在你的视图中。
-
我不得不使用{% if request.is_secure %}https://{% else %}http://{% endif %}{{ request.get_host }}{{ object.get_absolute_url }},因为{{ request.build_absolute_uri }}有一个尾部斜杠,{{ object.get_absolute_url }}以斜杠开头,导致URL中出现双斜杠。
-
如果get_absolute_url总是有一个前导斜杠,我觉得把它切成这样是更清晰:{{request.build_absolute_uri}} {{object.get_absolute_url | slice:"1:"}}
-
@minder要从Django-rest-framework获取请求,请在序列化函数函数中调用:request = self.context.get('request',None)
-
将字符串传递给函数会将字符串添加到绝对路径,而在字符串前面加上/将返回绝对路径,相对路径仅替换为字符串。示例request.get_full_path()返回/foo/bar/ request.build_full_uri('baz')返回http://domain.com/foo/bar/baz request.build_full_uri('/baz')返回http://domain.com/baz
-
我收到以下错误:ipdb> HttpRequest.build_absolute_uri(la_url) *** AttributeError: 'str' object has no attribute 'get_full_path'
-
@Velmont build_absolute_uri在没有传递参数时返回当前url。 {{ request.build_absolute_uri }}{{ object.get_absolute_url }}可能仅适用于主页,因为//被解释为/。
如果要将其与reverse()一起使用,可以执行以下操作:request.build_absolute_uri(reverse('view_name', args=(obj.pk, )))
-
谢谢你的回答。没有比编码本身更好的了。 (另外,你可能意味着url_name而不是view_name)
-
@Anupam reverse()定义为:def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)
您还可以使用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。
-
我相信我的问题专门说"没有网站模块"。这会打击数据库吗?
-
使用模块级缓存(即您不需要缓存框架)编写了Sites模块来缓存Site对象,因此只有在Web进程第一次检索到Site时才会触发DB。如果INSTALLED_APPS中没有django.contrib.sites,它将根本不会访问数据库,并根据Request对象提供信息(请参阅get_current_site)
-
那么你可以拥有+1,但build_absolute_uri仍然看起来更简单,更清洁的解决方案。
-
如果有Site.build_absolute_uri快捷方式,或者如果build_absolute_uri可以将None作为请求对象,那将会很好...
-
要避免使用TypeErros,您应该通过调用str来包装get_current_site(request),这样您就可以获得字符串而不是Site对象
-
如果您尝试在信号中生成URL以发送电子邮件,这是一个完美的答案。
-
如果您使用https,则不起作用。是的,您可以添加s,但是您是否在本地使用https进行开发?并且你总是知道,如果你有https但有时没有......?
-
get_current_site()依赖于对请求对象的访问,尽管您说"在请求对象不可用时可用"。如果没有访问请求,我们怎么做?
-
@shacker在那里的例子中,你可以传入request = None
-
对于本地测试目的,这是否意味着我需要为localhost添加一个站点并将相应的SITE_ID指向它?
如果您无法访问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
-
当您无权访问HttpRequest对象时,这非常方便。例如在任务,信号等
-
在使用它之前,你应该启用站点框架docs.djangoproject.com/en/dev/ref/contrib/sites/
如果您不想访问数据库,可以使用设置进行操作。然后,使用上下文处理器将其添加到每个模板:
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,让您用fullurl和fullstatic替换url和static模板标签,如下所示:
1 2 3 4 5
| {% load fullurl %}
Absolute URL is: {% fullurl"foo:bar" %}
Another absolute URL is: {% fullstatic"kitten.jpg" %} |
这些徽章应该有希望自动保持最新:
-
遗憾的是这不适用于2.0。可能需要推高PR。
-
@StevenChurch它应该工作。我还没有将Django 2.0标记为支持,但现有版本应该可以使用。
-
根据我的需要,我通过传递来自Heroku的ENV进行故障恢复来解决这个问题。我的问题是将URL传递给电子邮件模板。我不记得这个问题但由于Django的改变而无法解决问题。
-
@StevenChurch我认为创建电子邮件时的问题是没有request对象来获取域名。在这种情况下,您应该使用sites框架,它从数据库中获取域名。参见django-absoluteuri,在此PyPI包的自述文件的"另请参见"部分中提到。
-
谢谢,我会检查出来的!
还有另一种方式。您可以在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
-
HttpRequest.build_absolute_uri(request)相当于request.build_absolute_uri()不是吗?
-
@Mark是的,确实如此。
在您看来,只需这样做:
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。
-
答案是缺少协议(在此上下文中为http)和URL的://部分,因此它不会提供完整的URL。
-
请求对象上有一个主机。不要直接检查meta:docs.djangoproject.com/en/1.8/ref/request-response/
检查进来的Request.META字典。我认为它有服务器名称和服务器端口。
-
使用request.META ['HTTP_HOST']
-
请求对象上有一个主机。不要直接检查meta:docs.djangoproject.com/en/1.8/ref/request-response/
我知道这是一个老问题。但我认为人们仍然会遇到这种情况。
有几个库可以补充默认的Django功能。我试了几个。反向引用绝对URL时,我喜欢以下库:
https://github.com/fusionbox/django-absoluteuri
我喜欢的另一个因为你可以轻松地将域,协议和路径放在一起是:
https://github.com/RRMoelker/django-full-url
这个库允许您简单地在模板中写下您想要的内容,例如:
请尝试以下代码:
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框架中提及可用性
-
我使用request=request收到错误。这似乎也没有记录请求docs.djangoproject.com/en/1.9/ref/urlresolvers/#reverse
-
我忘了提到这只有在你使用REST框架时才可用。好抓,我更新了我的答案。
-
是的,谢谢你 - 这就像django 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() |
这对我来说很好,
我不完全确定它是如何工作的。我相信这是一个更低级别,并将返回您的服务器主机名,这可能与您的用户用于访问您的页面的主机名不同。
-
是的..你指出了问题所在。主机名不一定与域名相同。
-
这解决了一个非常不同的问题。考虑具有多个网站的共享托管服务器 - 使用上面的代码,生成URL的所有网站都将指向主机,这可能不是任何正在运行的网站。
你可以尝试"request.get_full_path()"