如何在Django模板中获取我的网站的域名?

时间:2009-09-20 14:27:19

标签: python django django-templates

如何从Django模板中获取当前网站的域名?我已经尝试查看标签和过滤器,但没有任何内容。

17 个答案:

答案 0 :(得分:90)

如果您想要实际的HTTP主机标头,请参阅Daniel Roseman对@ Phsiao的回答的评论。另一种选择是,如果您使用的是contrib.sites framework,则可以在数据库中为站点设置规范域名(将请求域映射到具有正确SITE_ID的设置文件是您必须自己做的事情你的网络服务器设置)。在那种情况下,你正在寻找:

from django.contrib.sites.models import Site

current_site = Site.objects.get_current()
current_site.domain

如果要使用它,必须自己将current_site对象放入模板上下文中。如果您在整个地方使用它,可以将其打包在模板上下文处理器中。

答案 1 :(得分:72)

我发现了{{ request.get_host }}方法。

答案 2 :(得分:60)

我认为您想要的是访问请求上下文,请参阅RequestContext。

答案 3 :(得分:54)

补充Carl Meyer,您可以制作这样的上下文处理器:

module.context_processors.py

from django.conf import settings

def site(request):
    return {'SITE_URL': settings.SITE_URL}

local settings.py

SITE_URL = 'http://google.com' # this will reduce the Sites framework db call.

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
 )

模板返回url站点的上下文实例是{{SITE_URL}}

如果想要在上下文处理器中处理子域或SSL,您可以编写自己的rutine。

答案 4 :(得分:22)

我使用的上下文处理器的变体是:

from django.contrib.sites.shortcuts import get_current_site
from django.utils.functional import SimpleLazyObject


def site(request):
    return {
        'site': SimpleLazyObject(lambda: get_current_site(request)),
    }

SimpleLazyObject包装器确保仅在模板实际使用site对象时才会发生数据库调用。这将从管理页面中删除查询。它还会缓存结果。

并将其包含在以下设置中:

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
)

在模板中,您可以使用{{ site.domain }}获取当前域名。

编辑也支持协议切换,请使用:

def site(request):
    site = SimpleLazyObject(lambda: get_current_site(request))
    protocol = 'https' if request.is_secure() else 'http'

    return {
        'site': site,
        'site_root': SimpleLazyObject(lambda: "{0}://{1}".format(protocol, site.domain)),
    }

答案 5 :(得分:16)

我知道这个问题很老,但我偶然发现它正在寻找一种获取当前域名的pythonic方法。

def myview(request):
    domain = request.build_absolute_uri('/')[:-1]
    # that will build the complete domain: http://foobar.com

答案 6 :(得分:13)

快速而简单,但不适合生产:

(在视图中)

    request.scheme               # http or https
    request.META['HTTP_HOST']    # example.com
    request.path                 # /some/content/1/

(在模板中)

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

请务必使用RequestContext,如果您使用render就是这种情况。

不要相信生产中的request.META['HTTP_HOST']:该信息来自浏览器。相反,请使用@ CarlMeyer的回答

答案 7 :(得分:11)

当与{{ request.get_host }}设置一起使用时,

ALLOWED_HOSTS应该防止H​​TTP Host头攻击(在Django 1.4.4中添加)。

请注意,{{ request.META.HTTP_HOST }}没有相同的保护。请参阅docs

  

ALLOWED_HOSTS

     

表示此Django站点可以提供的主机/域名的字符串列表。这是一种防止HTTP Host header attacks的安全措施,即使在许多看似安全的Web服务器配置下也是如此。

     

...如果Host标题(或X-Forwarded-Host如果USE_X_FORWARDED_HOST已启用)与此列表中的任何值都不匹配,则django.http.HttpRequest.get_host()方法将引发{{ 1}}。

     

...此验证仅适用于SuspiciousOperation;如果您的代码直接从get_host()访问主机头,则您将绕过此安全保护。

至于在模板中使用request.META,模板呈现函数调用具有changed in Django 1.8,因此您不再需要直接处理request

以下是使用快捷功能RequestContext为视图呈现模板的方法:

render()

以下是如何为电子邮件呈现模板,IMO是您更需要主机价值的更常见情况:

from django.shortcuts import render

def my_view(request):
    ...
    return render(request, 'my_template.html', context)

以下是在电子邮件模板中添加完整网址的示例; request.scheme应该from django.template.loader import render_to_string def my_view(request): ... email_body = render_to_string( 'my_template.txt', context, request=request) http取决于您使用的内容:

https

答案 8 :(得分:8)

我使用自定义模板标记。添加到例如<your_app>/templatetags/site.py

# -*- coding: utf-8 -*-
from django import template
from django.contrib.sites.models import Site

register = template.Library()

@register.simple_tag
def current_domain():
    return 'http://%s' % Site.objects.get_current().domain

在这样的模板中使用它:

{% load site %}
{% current_domain %}

答案 9 :(得分:4)

如果您使用"request" context processor,并且正在使用Django sites framework,并且已安装Site middleware(即您的设置包括以下内容):

cat(paste0(new_content, collapse="\n"), file="foo.SAM", "\n")

...,那么您将在模板中使用INSTALLED_APPS = [ ... "django.contrib.sites", ... ] MIDDLEWARE = [ ... "django.contrib.sites.middleware.CurrentSiteMiddleware", ... ] 对象,并且该对象将以request的形式包含对当前Site的引用。然后,您可以使用以下模板在模板中检索域:

request.site

,站点名称为:

    {{request.site.domain}}

答案 10 :(得分:2)

与用户panchicore的回复类似,这是我在一个非常简单的网站上所做的。 它提供了一些变量并使其在模板上可用。

SITE_URL会保留example.com之类的值 SITE_PROTOCOL会保留httphttps之类的值 SITE_PROTOCOL_URL会保留http://example.comhttps://example.com之类的值 SITE_PROTOCOL_RELATIVE_URL会保留//example.com之类的值。

<强>模块/ context_processors.py

from django.conf import settings

def site(request):

    SITE_PROTOCOL_RELATIVE_URL = '//' + settings.SITE_URL

    SITE_PROTOCOL = 'http'
    if request.is_secure():
        SITE_PROTOCOL = 'https'

    SITE_PROTOCOL_URL = SITE_PROTOCOL + '://' + settings.SITE_URL

    return {
        'SITE_URL': settings.SITE_URL,
        'SITE_PROTOCOL': SITE_PROTOCOL,
        'SITE_PROTOCOL_URL': SITE_PROTOCOL_URL,
        'SITE_PROTOCOL_RELATIVE_URL': SITE_PROTOCOL_RELATIVE_URL
    }

<强> settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
 )

SITE_URL = 'example.com'

然后,在您的模板上,将其用作{{ SITE_URL }}{{ SITE_PROTOCOL }}{{ SITE_PROTOCOL_URL }}{{ SITE_PROTOCOL_RELATIVE_URL }}

答案 11 :(得分:2)

您可以使用request.build_absolute_uri()

默认情况下,它将返回完整路径。

但是如果您输入这样的参数:

request.build_absolute_uri('/')

这将返回域名。

答案 12 :(得分:1)

我想我们想要的是现有 url 标签的替代品,所以我写了一个新标签:

from django.template import Library
from django.urls     import reverse

@register.simple_tag(takes_context = True)
def fullURL(context, name, *args, **kwargs):
    request = context['request']
    return f'{request.scheme}://{request.get_host()}{reverse(name, args = args, kwargs = kwargs)}'

然后在你的模板中你可以有这个...

{% extends "myapp/email/email_base.html" %}

{% load mytags %} {# Replace mytags with whatever the name of your custom tags calss is. #}

{% block content %}
<p>You can use <a href="{% fullURL 'signup' %}">this link</a> to get started with your account. We look forward to seeing you soon!</p>
{% endblock content %}

然后当你生成这个时,你只需要记住将 request 传递到 context,就像这样......

from django.template.loader import render_to_string

def sendEmail(subject, to, template, **context):
    html = render_to_string(f'myapp/email/{template}.html', context | {'subject': subject})
    # ... and so on with the rest of my function for sending email...

答案 13 :(得分:0)

这种方法怎么样?适合我。 它也用于django-registration

def get_request_root_url(self):
    scheme = 'https' if self.request.is_secure() else 'http'
    site = get_current_site(self.request)
    return '%s://%s' % (scheme, site)

答案 14 :(得分:0)

在Django模板中,您可以执行以下操作:

<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>

答案 15 :(得分:0)

from django.contrib.sites.models import Site
if Site._meta.installed:
    site = Site.objects.get_current()
else:
    site = RequestSite(request)

答案 16 :(得分:-4)

您可以在模板中使用{{ protocol }}://{{ domain }}来获取您的域名。