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

148 python django django-templates

如何从Django模板中获取当前站点的域名?我试过看标签和过滤器,但没有.

Car*_*yer 96

如果你想要实际的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
Run Code Online (Sandbox Code Playgroud)

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

  • 为了澄清与我有同样问题的人:检查你的`SITE_ID`设置是否等于站点应用程序中当前站点的`id`属性(你可以在站点管理面板中找到`id`).当你调用`get_current`时,Django会获取你的`SITE_ID`并从数据库中返回带有该id的`Site`对象. (3认同)

dan*_*gge 77

我发现了这种{{ request.get_host }}方法.

  • 请注意,这个答案与Daniel Roseman方法有相同的问题(它可以被欺骗),但是当通过HTTP代理或负载均衡器访问主机时它肯定会更完整,因为它考虑了`HTTP_X_FORWARDED_HOST` HTTP标头. (8认同)
  • 用法:"// {{request.get_host}}/anything/else/you/want"...请务必填写ALLOWED_HOSTS设置(请参阅https://docs.djangoproject.com/en/1.5/ref/设置/#允许的主机). (3认同)
  • @Seth更好地使用`request.build_absolute_uri`(https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.build_absolute_uri) (2认同)

小智 61

我想你想要的是访问请求上下文,请参阅RequestContext.

  • `request.META ['HTTP_HOST']`为您提供域名.在模板中,它将是`{{request.META.HTTP_HOST}}`. (128认同)
  • 使用请求元数据时要小心.它来自浏览器,可以欺骗.一般来说,你可能想要使用@CarlMeyer下面建议的内容. (29认同)
  • 我想,因为Django 1.5与允许的主机设置它是安全的使用.https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts (7认同)
  • 有人可以详细说明"安全漏洞"是什么吗?如果用户欺骗了`Host:`标头并在页面的某个地方获得了欺骗域的回复,那么它是如何创建安全漏洞的呢?我没有看到这与用户在将其提供给自己的浏览器之前采用生成的HTML并修改自己有何不同. (7认同)
  • 就我的目的而言,这没有任何安全漏洞. (2认同)

pan*_*ore 58

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

module.context_processors.py

from django.conf import settings

def site(request):
    return {'SITE_URL': settings.SITE_URL}
Run Code Online (Sandbox Code Playgroud)

本地settings.py

SITE_URL = 'http://google.com' # this will reduce the Sites framework db call.
Run Code Online (Sandbox Code Playgroud)

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
 )
Run Code Online (Sandbox Code Playgroud)

模板返回上下文实例的网址是{{SITE_URL}}

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


vdb*_*oor 24

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

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)),
    }
Run Code Online (Sandbox Code Playgroud)

SimpleLazyObject包装可以确保DB调用只有当模板实际使用情况site的对象.这将从管理页面中删除查询.它还缓存了结果.

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

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
)
Run Code Online (Sandbox Code Playgroud)

在模板中,您可以使用{{ 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)),
    }
Run Code Online (Sandbox Code Playgroud)


mis*_*rte 18

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

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

  • `build_absolute_uri`记录在案[这里](https://docs.djangoproject.com/en/stable/ref/request-response/#django.http.HttpRequest.build_absolute_uri). (4认同)

Edw*_*ell 17

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

(在视图中)

    request.scheme               # http or https
    request.META['HTTP_HOST']    # example.com
    request.path                 # /some/content/1/
Run Code Online (Sandbox Code Playgroud)

(在模板中)

{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}
Run Code Online (Sandbox Code Playgroud)

一定要使用RequestContext,如果你使用的是渲染.

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


S. *_*rby 13

{{ request.get_host }}当与ALLOWED_HOSTS设置一起使用时,应该防止H​​TTP Host头攻击(在Django 1.4.4中添加).

请注意,{{ request.META.HTTP_HOST }}没有相同的保护.查看文档:

ALLOWED_HOSTS

表示此Django站点可以提供的主机/域名的字符串列表.这是一种防止HTTP主机头攻击的安全措施,即使在许多看似安全的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)
Run Code Online (Sandbox Code Playgroud)

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

from django.template.loader import render_to_string

def my_view(request):
    ...
    email_body = render_to_string(
        'my_template.txt', context, request=request)
Run Code Online (Sandbox Code Playgroud)

以下是在电子邮件模板中添加完整网址的示例; request.scheme应该得到httphttps取决于你使用的是什么:

Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
Run Code Online (Sandbox Code Playgroud)


use*_*461 9

If you use the "request" context processor, and are using the Django sites framework, and have the Site middleware installed (i.e. your settings include these):

INSTALLED_APPS = [
    ...
    "django.contrib.sites",
    ...
]

MIDDLEWARE = [
    ...
     "django.contrib.sites.middleware.CurrentSiteMiddleware",
    ...
]
Run Code Online (Sandbox Code Playgroud)

... then you will have the request object available in templates, and it will contain a reference to the current Site for the request as request.site. You can then retrieve the domain in a template with:

    {{request.site.domain}}
Run Code Online (Sandbox Code Playgroud)

and the site name with:

    {{request.site.name}}
Run Code Online (Sandbox Code Playgroud)


Den*_*zov 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
Run Code Online (Sandbox Code Playgroud)

在这样的模板中使用它:

{% load site %}
{% current_domain %}
Run Code Online (Sandbox Code Playgroud)

  • `'http://%s'`在`https`连接的情况下可能是个问题; 在这种情况下,方案不是动态的. (2认同)

Jul*_*che 6

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

SITE_URL将持有一个值 likeexample.com
SITE_PROTOCOL将持有一个值 likehttphttps
SITE_PROTOCOL_URL将持有一个值 likehttp://example.comhttps://example.com
SITE_PROTOCOL_RELATIVE_URL将持有一个值 like //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
    }
Run Code Online (Sandbox Code Playgroud)

设置.py

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

SITE_URL = 'example.com'
Run Code Online (Sandbox Code Playgroud)

然后,在你的模板,把它们作为{{ SITE_URL }}{{ SITE_PROTOCOL }}{{ SITE_PROTOCOL_URL }}{{ SITE_PROTOCOL_RELATIVE_URL }}


小智 6

您可以使用request.build_absolute_uri()

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

但如果你传入这样的参数:

request.build_absolute_uri('/')
Run Code Online (Sandbox Code Playgroud)

这将返回域名。