https://example.com/some/path
在没有Sites模块的情况下,如何在Django中获取完整/绝对URL(例如)?那真是愚蠢……我不需要查询数据库来获取URL!
我想用它reverse()
。
https://example.com/some/path
在没有Sites模块的情况下,如何在Django中获取完整/绝对URL(例如)?那真是愚蠢……我不需要查询数据库来获取URL!
我想用它reverse()
。
Answers:
根据请求使用方便的request.build_absolute_uri()方法,向其传递相对网址,它将为您提供完整的URL。
默认情况下,request.get_full_path()
返回的绝对URL ,但是您可以将相对URL作为第一个参数传递给它,以将其转换为绝对URL。
{{ request.build_absolute_uri }}{{ object.get_absolute_url }}
-嘿,完整的url。
{% if request.is_secure %}https://{% else %}http://{% endif %}{{ request.get_host }}{{ object.get_absolute_url }}
因为{{ request.build_absolute_uri }}
它后面有一个斜杠,{{ object.get_absolute_url }}
并以斜杠开头,导致URL中出现双斜杠。
如果要与它一起使用,reverse()
可以执行以下操作:request.build_absolute_uri(reverse('view_name', args=(obj.pk, )))
url_name
代替view_name
)
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)
您也可以将其get_current_site
用作网站应用程序(from django.contrib.sites.models import get_current_site
)的一部分。它接受一个请求对象,SITE_ID
如果request为,则默认为您在settings.py中配置的站点对象None
。在使用站点框架的文档中阅读更多内容
例如
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时,它可以使用。
django.contrib.sites
在你的INSTALLED_APPS
,也不会打DB可言,并提供基于Request对象的信息(见get_current_site)
build_absolute_uri
看起来仍然是更简单,更干净的解决方案。
如果无法访问,request
则无法get_current_site(request)
按此处某些解决方案中的建议使用。您可以使用本机Sites框架的组合来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/zh-CN/dev/ref/contrib/sites/#getting-the-current-domain-for-full-urls
request
为None
或致电get_current_site(None)
。
如果您不想访问数据库,则可以通过设置来完成。然后,使用上下文处理器将其添加到每个模板中:
# 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
让你更换url
并static
用模板标签fullurl
和fullstatic
,如下所示:
{% load fullurl %}
Absolute URL is: {% fullurl "foo:bar" %}
Another absolute URL is: {% fullstatic "kitten.jpg" %}
这些徽章有望自动保持最新状态:
在视图中,您当然可以request.build_absolute_uri
代替使用。
request
对象可以获取域名。在这种情况下,您应该改用sites
框架,该框架从数据库获取域名。请参见django-absoluteuri
,在此PyPI软件包的自述文件的“另请参见”部分中提到。
要创建从模板到另一个页面的完整链接,可以使用以下方法:
{{ request.META.HTTP_HOST }}{% url 'views.my_view' my_arg %}
request.META.HTTP_HOST提供主机名,而url提供相对名。然后,模板引擎将它们串联成一个完整的URL。
http
在这种情况下)和://
URL的一部分,因此它不会提供完整的url。
还有另一种方式。您可以build_absolute_uri()
在其中使用view.py
并将其传递给模板。
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)
等于request.build_absolute_uri()
不是吗?
检查其中的Request.META
字典。我认为它具有服务器名称和服务器端口。
这在我的模板中对我有用:
{{ request.scheme }}:{{ request.META.HTTP_HOST }}{% url 'equipos:marca_filter' %}
我需要完整的网址才能将其传递给js提取函数。希望对您有所帮助。
我知道这是一个老问题。但是我认为人们仍然会遇到很多问题。
有一些库可以补充默认的Django功能。我已经尝试了一些。当反向引用绝对URL时,我喜欢以下库:
https://github.com/fusionbox/django-absoluteuri
我喜欢的另一个参数是因为您可以轻松地将域,协议和路径组合在一起:
https://github.com/RRMoelker/django-full-url
该库使您可以简单地在模板中编写所需内容,例如:
{{url_parts.domain}}
如果您使用的是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框架中的可用性
还提供ABSOLUTE_URL_OVERRIDES作为设置
https://docs.djangoproject.com/zh-CN/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()
对其进行子类化,现在您可以在任何地方使用它。
如其他答案所述,request.build_absolute_uri()
如果您可以访问request
和sites
只要不同的URL指向不同的数据库框架就很好。
但是,我的用例略有不同。我的登台服务器和生产服务器访问相同的数据库,但是get_current_site
都返回site
了数据库中的第一个数据库。若要解决此问题,您必须使用某种环境变量。您可以为不同的服务器和不同的settings.py使用1)环境变量(类似os.environ.get('SITE_URL', 'localhost:8000')
)或2)different 。SITE_ID
希望有人会发现这个有用!
您还可以使用:
import socket
socket.gethostname()
这对我来说很好
我不完全确定它是如何工作的。我相信这是一个较低的级别,它将返回您的服务器主机名,该主机名可能与用户访问页面所使用的主机名不同。