如何从Django模板中获取当前站点的域名?我试着寻找标签和过滤器,但那里什么也没有。
如何从Django模板中获取当前站点的域名?我试着寻找标签和过滤器,但那里什么也没有。
Answers:
我认为您想要的是可以访问请求上下文,请参见RequestContext。
Host:标头并在页面上某处获得带有欺骗域的响应,那将如何创建安全漏洞?我看不出这与用户采用生成的HTML并在将其馈送到其自己的浏览器之前对其进行修改之前不同。
                    如果需要实际的HTTP Host标头,请参阅Daniel Roseman对@Phsiao答案的评论。另一种选择是,如果您使用的是contrib.sites框架,则可以在数据库中为站点设置一个规范域名(将请求域映射到具有正确SITE_ID的设置文件中,这是您必须通过自己的网络服务器设置)。在这种情况下,您要寻找:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain如果要使用current_site对象,则必须自己将其放在模板上下文中。如果您在各处使用它,则可以将其打包在模板上下文处理器中。
SITE_ID设置是否等于“ id网站”应用中当前网站的属性(您可以id在“网站”管理面板中找到)。当您调用时get_current,Django会使用SITE_ID并Site从数据库返回具有该ID 的对象。
                    print("get_current_site: ", get_current_site(request))     print("absolute uri: ", request.build_absolute_uri())     print("HTTP_HOST: ", request.META['HTTP_HOST']) get_current_site:  localhost:8001 absolute uri: http://localhost:8001/... HTTP_HOST:  localhost:8001
                    我发现了{{ request.get_host }}方法。
HTTP_X_FORWARDED_HOSTHTTP标头,因此肯定更完整。
                    request.build_absolute_uri(docs.djangoproject.com/en/dev/ref/request-response/...)
                    作为对Carl Meyer的补充,您可以像这样创建一个上下文处理器:
from django.conf import settings
def site(request):
    return {'SITE_URL': settings.SITE_URL}SITE_URL = 'http://google.com' # this will reduce the Sites framework db call.TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
 )如果要在上下文处理器中处理子域或SSL,则可以编写自己的例程。
我使用的上下文处理器的变体是:
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)),
    }SimpleLazyObject这里使用,因为如果没有人访问“站点”,则不会调用lambda。
                    SimpleLazyObject,每个RequestContext将调用get_current_site(),并因此执行SQL查询。包装器确保仅在模板中实际使用变量时才评估该变量。
                    SimpleLazyObject目的是避免的功能,这是不是真的需要,因为重新评估Site对象缓存。
                    from django.contrib.sites.shortcuts import get_current_site
                    我知道这个问题很老,但是我偶然发现了这个问题,寻找一种获取当前域的pythonic方法。
def myview(request):
    domain = request.build_absolute_uri('/')[:-1]
    # that will build the complete domain: http://foobar.combuild_absolute_uri记录在这里。
                    快速简单,但不适用于生产:
(在视图中)
    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的答案
request.scheme。也许仅在django的较新版本中可用。
                    request.scheme是在Django 1.7中添加的。
                    {{ request.get_host }}与ALLOWED_HOSTS设置(在Django 1.4.4中添加)一起使用时,应该可以防止HTTP Host标头攻击。
请注意,{{ request.META.HTTP_HOST }}没有相同的保护。见文档:
ALLOWED_HOSTS
代表此Django站点可以服务的主机/域名的字符串列表。这是一种安全措施,可以防止HTTP Host标头攻击,即使在许多看似安全的Web服务器配置下也可能发生这种攻击。
...如果
Host标头(或者X-Forwarded-Host如果USE_X_FORWARDED_HOST使能)不匹配,在此列表中的任何值,该django.http.HttpRequest.get_host()方法将提高SuspiciousOperation。...此验证仅通过进行
get_host();如果您的代码直接从request.META您访问Host标头,则绕过此安全保护措施。
至于request在模板中使用,在Django 1.8中,模板渲染函数调用已更改,因此您不再需要RequestContext直接处理。
这是使用快捷功能为视图渲染模板的方法render():
from django.shortcuts import render
def my_view(request):
    ...
    return render(request, 'my_template.html', context)这是呈现电子邮件模板的方法,在您需要主机值的情况下,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的示例;request.scheme应该获得http或https取决于您使用的是什么:
Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}我使用自定义模板标签。添加到例如<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 %}get_current是一种记录方法:docs.djangoproject.com/en/dev/ref/contrib/sites/...
                    'http://%s'在https连接的情况下可能是一个问题;在这种情况下,方案不是动态的。
                    与用户panchicore的回复类似,这是我在一个非常简单的网站上所做的。它提供了一些变量并使它们在模板上可用。
SITE_URL将举行一个类似的值example.com
SITE_PROTOCOL将举行类似的值http  或https
SITE_PROTOCOL_URL将举行类似的值http://example.com或https://example.com
SITE_PROTOCOL_RELATIVE_URL将持有的值等//example.com。
module / 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>django.template.context_processors.request也[这如何做帮助(simpleisbetterthancomplex.com/tips/2016/07/20/...)
                    如果您使用“请求”上下文处理器,并且正在使用Django sites框架,并且安装了Site中间件(即您的设置包括以下内容):
INSTALLED_APPS = [
    ...
    "django.contrib.sites",
    ...
]
MIDDLEWARE = [
    ...
     "django.contrib.sites.middleware.CurrentSiteMiddleware",
    ...
]
TEMPLATES = [
    {
        ...
        "OPTIONS": {
            "context_processors": [
                ...
                "django.template.context_processors.request",
                ...
            ]
        }
    }
]...然后您将request在模板中使用该对象,并且该对象将包含对当前Site请求的引用request.site。然后,您可以使用以下模板在模板中检索域:
    {{request.site.domain}}那这种方法呢?为我工作。它也用于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)localhost会为您提供一个https方案(它被认为是安全的),如果您具有静态url(仅http://127.0.0.1有效,则不是https://127.0.0.1),该方案将不起作用。因此,当仍在开发中时,它并不理想。
                    from django.contrib.sites.models import Site
if Site._meta.installed:
    site = Site.objects.get_current()
else:
    site = RequestSite(request)您可以{{ protocol }}://{{ domain }}在模板中使用来获取域名。
request.META['HTTP_HOST']给您域名。在模板中应该是{{ request.META.HTTP_HOST }}。