418

我在 settings.py 中有一些我希望能够从模板访问的东西,但我不知道该怎么做。我已经试过了

{{CONSTANT_NAME}}

但这似乎不起作用。这可能吗?

4

16 回答 16

493

如果您希望每个请求和模板都具有该值,则使用上下文处理器更合适。

就是这样:

  1. 在您的应用程序目录中创建一个context_processors.py文件。假设我想ADMIN_PREFIX_VALUE在每种情况下都具有价值:

    from django.conf import settings # import the settings file
    
    def admin_media(request):
        # return the value you want as a dictionnary. you may add multiple values in there.
        return {'ADMIN_MEDIA_URL': settings.ADMIN_MEDIA_PREFIX}
    
  2. 将您的上下文处理器添加到您的settings.py文件中:

    TEMPLATES = [{
        # whatever comes before
        'OPTIONS': {
            'context_processors': [
                # whatever comes before
                "your_app.context_processors.admin_media",
            ],
        }
    }]
    
  3. RequestContext在您的视图中使用以在模板中添加上下文处理器。render快捷方式会自动执行此操作:

    from django.shortcuts import render
    
    def my_view(request):
        return render(request, "index.html")
    
  4. 最后,在您的模板中:

    ...
    <a href="{{ ADMIN_MEDIA_URL }}">path to admin media</a>
    ...
    
于 2009-01-11T17:01:03.927 回答
316

我发现最简单的方法是单个自定义模板标签

from django import template
from django.conf import settings

register = template.Library()

# settings value
@register.simple_tag
def settings_value(name):
    return getattr(settings, name, "")

用法:

{% settings_value "LANGUAGE_CODE" %}
于 2011-10-10T16:58:19.407 回答
197

settings.MEDIA_URL如果您使用 django 的内置通用视图或在render_to_response快捷函数中传入上下文实例关键字参数, Django 提供对模板的某些常用设置常量的访问,例如和一些语言设置。以下是每种情况的示例:

from django.shortcuts import render_to_response
from django.template import RequestContext
from django.views.generic.simple import direct_to_template

def my_generic_view(request, template='my_template.html'):
    return direct_to_template(request, template)

def more_custom_view(request, template='my_template.html'):
    return render_to_response(template, {}, context_instance=RequestContext(request))

这些视图都将有几个常用的设置settings.MEDIA_URL,例如模板可用{{ MEDIA_URL }}等。

如果您正在寻找对设置中其他常量的访问,则只需解压缩所需的常量并将它们添加到您在视图函数中使用的上下文字典中,如下所示:

from django.conf import settings
from django.shortcuts import render_to_response

def my_view_function(request, template='my_template.html'):
    context = {'favorite_color': settings.FAVORITE_COLOR}
    return render_to_response(template, context)

现在您可以settings.FAVORITE_COLOR在您的模板上以{{ favorite_color }}.

于 2009-01-11T17:28:50.500 回答
107

退房django-settings-export(免责声明:我是这个项目的作者)。

例如...

$ pip install django-settings-export

设置.py

TEMPLATES = [
    {
        'OPTIONS': {
            'context_processors': [
                'django_settings_export.settings_export',
            ],
        },
    },
]

MY_CHEESE = 'Camembert';

SETTINGS_EXPORT = [
    'MY_CHEESE',
]

模板.html

<script>var MY_CHEESE = '{{ settings.MY_CHEESE }}';</script>
于 2014-09-15T04:54:35.297 回答
47

另一种方法是创建一个自定义模板标签,它可以让您从设置中提取值。

@register.tag
def value_from_settings(parser, token):
    try:
        # split_contents() knows not to split quoted strings.
        tag_name, var = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0]
    return ValueFromSettings(var)

class ValueFromSettings(template.Node):
    def __init__(self, var):
        self.arg = template.Variable(var)
    def render(self, context):        
        return settings.__getattr__(str(self.arg))

然后你可以使用:

{% value_from_settings "FQDN" %}

将其打印在任何页面上,而无需跳过上下文处理器箍。

于 2011-03-08T16:53:00.217 回答
32

我喜欢 Berislav 的解决方案,因为在简单的网站上,它既干净又有效。我不喜欢随意公开所有设置常量。所以我最终做的是:

from django import template
from django.conf import settings

register = template.Library()

ALLOWABLE_VALUES = ("CONSTANT_NAME_1", "CONSTANT_NAME_2",)

# settings value
@register.simple_tag
def settings_value(name):
    if name in ALLOWABLE_VALUES:
        return getattr(settings, name, '')
    return ''

用法:

{% settings_value "CONSTANT_NAME_1" %}

这可以保护您没有在模板中使用的任何未命名的常量,如果您想要真正花哨,您可以在设置中设置一个元组,并为不同的页面、应用程序或区域创建多个模板标签,并且只需根据需要将本地元组与设置元组组合,然后执行列表推导以查看该值是否可以接受。
我同意,在一个复杂的网站上,这有点简单,但是有些值可以很好地普遍存在于模板中,这似乎很好用。感谢 Berislav 的原创想法!

于 2014-02-06T03:45:55.783 回答
17

使用 Django 2.0+ 添加包含创建自定义模板标签的完整说明的答案以解决此问题

在您的 app-folder 中,创建一个名为templatetags的文件夹。在其中创建__init__.pycustom_tags.py

自定义标签文件夹结构

custom_tags.py中创建一个自定义标签函数,该函数提供对设置常量中任意键的访问:

from django import template
from django.conf import settings

register = template.Library()

@register.simple_tag
def get_setting(name):
    return getattr(settings, name, "")

为了理解这段代码,我建议阅读Django 文档中关于简单标签的部分。

然后,您需要通过将这个文件加载到您将使用它的任何模板中来让 Django 知道这个(以及任何附加的)自定义标签。就像您需要加载内置的静态标签一样:

{% load custom_tags %}

加载后,它可以像任何其他标签一样使用,只需提供您需要返回的特定设置。因此,如果您的设置中有 BUILD_VERSION 变量:

{% get_setting "BUILD_VERSION" %}

此解决方案不适用于数组,但如果您需要,您可能会在模板中添加大量逻辑。

注意:一个更干净和故障安全的解决方案可能是制作一个自定义上下文处理器,您可以在其中将所需的设置添加到所有模板都可用的上下文中。这样,您就可以降低在模板中错误地输出敏感设置的风险。

于 2018-04-25T09:45:52.493 回答
16

将此代码添加到名为的文件中context_processors.py

from django.conf import settings as django_settings


def settings(request):
    return {
        'settings': django_settings,
    }

然后,在您的设置文件'speedy.core.base.context_processors.settings'中,'context_processors'TEMPLATES.

(例如,您可以看到settings/base.pycontext_processors.py)。

然后您可以在任何模板代码中使用特定设置。例如:

{% if settings.SITE_ID == settings.SPEEDY_MATCH_SITE_ID %}

更新:上面的代码向模板公开了所有设置,包括敏感信息,例如您的SECRET_KEY. 黑客可能会滥用此功能在模板中显示此类信息。如果您只想向模板公开特定设置,请改用以下代码:

def settings(request):
    settings_in_templates = {}
    for attr in ["SITE_ID", ...]: # Write here the settings you want to expose to the templates.
        if (hasattr(django_settings, attr)):
            settings_in_templates[attr] = getattr(django_settings, attr)
    return {
        'settings': settings_in_templates,
    }
于 2018-12-28T04:09:09.923 回答
13

我稍微改进了chrisdew的答案(创建自己的标签)。

首先,创建yourapp/templatetags/value_from_settings.py您定义自己的新标签的文件value_from_settings

from django.template import TemplateSyntaxError, Variable, Node, Variable, Library
from yourapp import settings

register = Library()
# I found some tricks in URLNode and url from defaulttags.py:
# https://code.djangoproject.com/browser/django/trunk/django/template/defaulttags.py
@register.tag
def value_from_settings(parser, token):
  bits = token.split_contents()
  if len(bits) < 2:
    raise TemplateSyntaxError("'%s' takes at least one " \
      "argument (settings constant to retrieve)" % bits[0])
  settingsvar = bits[1]
  settingsvar = settingsvar[1:-1] if settingsvar[0] == '"' else settingsvar
  asvar = None
  bits = bits[2:]
  if len(bits) >= 2 and bits[-2] == 'as':
    asvar = bits[-1]
    bits = bits[:-2]
  if len(bits):
    raise TemplateSyntaxError("'value_from_settings' didn't recognise " \
      "the arguments '%s'" % ", ".join(bits))
  return ValueFromSettings(settingsvar, asvar)

class ValueFromSettings(Node):
  def __init__(self, settingsvar, asvar):
    self.arg = Variable(settingsvar)
    self.asvar = asvar
  def render(self, context):
    ret_val = getattr(settings,str(self.arg))
    if self.asvar:
      context[self.asvar] = ret_val
      return ''
    else:
      return ret_val

您可以通过以下方式在模板中使用此标签:

{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" %}

或通过

{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" as my_fqdn %}

as ...符号的优点在于,这使得blocktrans通过简单的{{my_fqdn}}.

于 2011-06-14T12:16:23.747 回答
9

如果使用基于类的视图:

#
# in settings.py
#
YOUR_CUSTOM_SETTING = 'some value'

#
# in views.py
#
from django.conf import settings #for getting settings vars

class YourView(DetailView): #assuming DetailView; whatever though

    # ...

    def get_context_data(self, **kwargs):

        context = super(YourView, self).get_context_data(**kwargs)
        context['YOUR_CUSTOM_SETTING'] = settings.YOUR_CUSTOM_SETTING

        return context

#
# in your_template.html, reference the setting like any other context variable
#
{{ YOUR_CUSTOM_SETTING }}
于 2013-04-28T22:38:13.487 回答
8

上面来自 bchhun 的示例很好,只是您需要从 settings.py 显式构建上下文字典。下面是一个未经测试的示例,说明如何从 settings.py 的所有大写属性自动构建上下文字典(re: "^[A-Z0-9_]+$")。

在 settings.py 的末尾:

_context = {} 
local_context = locals()
for (k,v) in local_context.items():
    if re.search('^[A-Z0-9_]+$',k):
        _context[k] = str(v)

def settings_context(context):
    return _context

TEMPLATE_CONTEXT_PROCESSORS = (
...
'myproject.settings.settings_context',
...
)
于 2011-03-28T13:45:44.497 回答
8

如果有人像我一样发现这个问题,那么我将发布适用于 Django 2.0 的解决方案:

此标记将一些 settings.py 变量值分配给模板的变量:

用法:{% get_settings_value template_var "SETTINGS_VAR" %}

应用程序/模板标签/my_custom_tags.py:

from django import template
from django.conf import settings

register = template.Library()

class AssignNode(template.Node):
    def __init__(self, name, value):
        self.name = name
        self.value = value

    def render(self, context):
        context[self.name] = getattr(settings, self.value.resolve(context, True), "")
        return ''

@register.tag('get_settings_value')
def do_assign(parser, token):
    bits = token.split_contents()
    if len(bits) != 3:
        raise template.TemplateSyntaxError("'%s' tag takes two arguments" % bits[0])
    value = parser.compile_filter(bits[2])
    return AssignNode(bits[1], value)

您的模板:

{% load my_custom_tags %}

# Set local template variable:
{% get_settings_value settings_debug "DEBUG" %}

# Output settings_debug variable:
{{ settings_debug }}

# Use variable in if statement:
{% if settings_debug %}
... do something ...
{% else %}
... do other stuff ...
{% endif %}

请参阅 Django 的文档如何在此处创建自定义模板标签:https ://docs.djangoproject.com/en/2.0/howto/custom-template-tags/

于 2018-01-17T13:56:51.330 回答
3

我发现这是 Django 1.3 最简单​​的方法:

  1. 视图.py

    from local_settings import BASE_URL
    
    def root(request):
        return render_to_response('hero.html', {'BASE_URL': BASE_URL})
    
  2. 英雄.html

    var BASE_URL = '{{ JS_BASE_URL }}';
    
于 2013-08-23T19:06:53.790 回答
2

对于那些想要使用带有标签的@Berislav 方法(自定义模板标签)的人if

/app/templatetags/my_settings.py:

from django import template
from django.conf import settings

register = template.Library()

@register.simple_tag
def settings_value(name):
    return getattr(settings, name, "")

模板文件:

<!-- Load your tags -->
{% load my_settings %}
{% settings_value 'ENABLE_FEATURE_A' as ENABLE_FEATURE_A %}

{% if ENABLE_FEATURE_A %}
<!-- Feature A stuffs -->
{% endif %}
于 2021-09-30T22:22:51.403 回答
1

IanSR 和 bchhun 都建议在设置中覆盖 TEMPLATE_CONTEXT_PROCESSORS。请注意,此设置有一个默认值,如果您在不重新设置默认值的情况下覆盖它,可能会导致一些麻烦的事情。在最新版本的 Django 中,默认值也发生了变化。

https://docs.djangoproject.com/en/1.3/ref/settings/#template-context-processors

默认的 TEMPLATE_CONTEXT_PROCESSORS :

TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"django.contrib.messages.context_processors.messages")
于 2011-11-23T16:20:51.717 回答
1

如果我们要比较单个变量上的上下文和模板标签,那么了解更有效的选项可能是有益的。但是,您最好只从需要该变量的模板中深入了解设置。在这种情况下,将变量传递给所有模板是没有意义的。但是,如果您将变量发送到通用模板(例如 base.html 模板)中,那么 base.html 模板会在每个请求上呈现,因此您可以使用任何一种方法。

如果您决定使用模板标签选项,请使用以下代码,因为它允许您传入默认值,以防有问题的变量未定义。

示例:get_from_settings my_variable as my_context_value

示例:get_from_settings my_variable my_default as my_context_value

class SettingsAttrNode(Node):
    def __init__(self, variable, default, as_value):
        self.variable = getattr(settings, variable, default)
        self.cxtname = as_value

    def render(self, context):
        context[self.cxtname] = self.variable
        return ''


def get_from_setting(parser, token):
    as_value = variable = default = ''
    bits = token.contents.split()
    if len(bits) == 4 and bits[2] == 'as':
        variable = bits[1]
        as_value = bits[3]
    elif len(bits) == 5 and bits[3] == 'as':
        variable     = bits[1]
        default  = bits[2]
        as_value = bits[4]
    else:
        raise TemplateSyntaxError, "usage: get_from_settings variable default as value " \
                "OR: get_from_settings variable as value"

    return SettingsAttrNode(variable=variable, default=default, as_value=as_value)

get_from_setting = register.tag(get_from_setting)
于 2011-12-11T05:29:49.060 回答