如何从Django模板中获取当前站点的域名?我试着在标签和过滤器中寻找,但没有什么。


当前回答

这种方法怎么样?对我有用。 它也用于django注册。

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)

其他回答

如果您想要实际的HTTP Host报头,请参阅Daniel Roseman对@Phsiao的回答的评论。另一种选择是使用contrib。sites框架,你可以在数据库中为站点设置一个规范的域名(将请求域映射到一个具有正确SITE_ID的设置文件是你必须通过你的webserver设置自己做的事情)。在这种情况下,你要寻找:

from django.contrib.sites.models import Site

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

如果您想使用current_site对象,则必须自己将其放入模板上下文中。如果你到处都在使用它,你可以把它打包到一个模板上下文处理器中。

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

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调用。这将从管理页面中删除查询。它还缓存结果。

并将其包含在设置中:

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)),
    }

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

SITE_URL将保存类似example.com的值 SITE_PROTOCOL将保存类似http或https的值 SITE_PROTOCOL_URL将包含http://example.com或https://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}}

在Django模板中,你可以这样做:

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

我认为我们想要的是现有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 %}

然后,当你生成这个时,你只需要记住将请求传递到上下文,就像这样……

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