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

Python 如何在Django模板中获取我的站点的域名?,python,django,django-templates,Python,Django,Django Templates,如何从Django模板中获取当前站点的域名?我试着查看标记和过滤器,但没有找到任何内容。我认为您想要的是访问请求上下文,请参阅RequestContext。如果您想要实际的HTTP主机头,请参阅Daniel Roseman对@Phsiao答案的评论。另一种选择是,如果使用,则可以为数据库中的站点设置规范域名(将请求域映射到具有正确站点ID的设置文件是您必须通过Web服务器设置自行完成的事情)。在这种情况下,您需要: from django.contrib.sites.models import

如何从Django模板中获取当前站点的域名?我试着查看标记和过滤器,但没有找到任何内容。

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

如果您想要实际的HTTP主机头,请参阅Daniel Roseman对@Phsiao答案的评论。另一种选择是,如果使用,则可以为数据库中的站点设置规范域名(将请求域映射到具有正确站点ID的设置文件是您必须通过Web服务器设置自行完成的事情)。在这种情况下,您需要:

from django.contrib.sites.models import Site

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

如果您想使用当前的站点对象,您必须自己将其放入模板上下文中。如果您到处使用它,您可以将其打包到模板上下文处理器中。

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

{% load site %}
{% current_domain %}
request.build_absolute_uri('/')
module.context_processors.py 本地设置.py 设置.py 返回上下文实例的模板url站点为{{site_url}}
如果要在上下文处理器中处理子域或SSL,可以编写自己的rutine。

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

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
包装器确保DB调用仅在模板实际使用
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)),
    }

我发现了这个方法。

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

我使用自定义模板标记。添加到例如
/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 %}
request.build_absolute_uri('/')

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

SITE\u URL
将包含类似
example.com

SITE\u协议
将包含类似于
http
https

SITE\u PROTOCOL\u URL
将包含类似
http://example.com
https://example.com

SITE\u PROTOCOL\u RELATIVE\u URL
将包含一个类似于
//example.com
的值

模块/上下文处理器.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
    }
TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
 )

SITE_URL = 'example.com'
设置.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
    }
TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
 )

SITE_URL = 'example.com'

然后,在模板上,使用它们作为
{{SITE\u URL}
{SITE\u PROTOCOL}
{SITE\u PROTOCOL\u URL}
{SITE\u PROTOCOL\u RELATIVE\u URL}
快速简单,但不利于生产:

(在视图中)

(在模板中)

确保使用a,如果您正在使用


不要信任生产中的
request.META['HTTP\u HOST']
:这些信息来自浏览器。相反,请使用@CarlMeyer的答案

我知道这个问题很老了,但我无意中发现了它,正在寻找一种pythonic方法来获取当前域

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

{{request.get_host}}
ALLOWED_HOSTS
设置(在Django 1.4.4中添加)一起使用时,应防止HTTP主机头攻击

请注意,
{{request.META.HTTP_HOST}
没有相同的保护。见:

允许的\u主机

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

。。。如果
Host
头(或
X-Forwarded-Host
如果
USE\u-Forwarded\u-Host
已启用)与此列表中的任何值不匹配,则
django.http.HttpRequest.get\u-Host()
方法将引发
可疑操作

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


至于在模板中使用
request
,模板呈现函数调用已经完成,因此您不再需要直接处理
RequestContext

下面介绍如何使用快捷方式函数
render()
,为视图渲染模板:

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

from django.template.loader import render_to_string

def my_view(request):
    ...
    email_body = render_to_string(
        'my_template.txt', context, request=request)
下面是在电子邮件模板中添加完整URL的示例;根据您所使用的内容,应获取
http
https

Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}

这种方法怎么样?对我有用。 它也被用在英语中


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

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

如果您使用和正在使用,并已安装(即,您的设置包括以下内容):

已安装的应用程序=[
...
“django.contrib.sites”,
...
]
中间件=[
...
“django.contrib.sites.middleware.CurrentSiteMiddleware”,
...
]
。。。然后,您将在模板中提供
请求
对象,并且它将包含对请求的当前
站点
的引用,即
请求.站点
。然后,您可以使用以下内容在模板中检索域:

    {{request.site.domain}}
以及网站名称,其中包含:

    {{request.site.name}}
你可以用

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

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

{% load site %}
{% current_domain %}
request.build_absolute_uri('/')

这将返回域名。

我想我们想要的是现有
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.META['HTTP\u HOST']
为您提供域。在模板中,它应该是
{{request.META.HTTP_HOST}}
。使用请求元数据时要小心。它来自浏览器,可以被欺骗。一般来说,您可能希望按照@CarlMeyer.F下面的建议进行操作
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 %}
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...