我在 settings.py 中有一些我希望能够从模板访问的东西,但我不知道该怎么做。我已经试过了
{{CONSTANT_NAME}}
但这似乎不起作用。这可能吗?
如果它是您希望为每个请求提供的值 &模板,使用 context processor 更合适。
就是这样:
在你的 app 目录中创建一个 context_processors.py 文件。假设我想在每个上下文中都有 ADMIN_PREFIX_VALUE 值: from django.conf import settings # import the settings file def admin_media(request): # return 你想要的值作为字典。您可以在其中添加多个值。 return {'ADMIN_MEDIA_URL': settings.ADMIN_MEDIA_PREFIX} 将您的上下文处理器添加到您的 settings.py 文件中: TEMPLATES = [{ # 'OPTIONS' 之前的任何内容:{ 'context_processors': [ # "your_app.context_processors.admin_media" 之前的任何内容, ], } }] 在你的视图中使用 RequestContext 在你的模板中添加你的上下文处理器。渲染快捷方式自动执行此操作: from django.shortcuts import render def my_view(request): return render(request, "index.html") 最后,在您的模板中: ... 管理媒体路径 ...
我发现最简单的方法是单个 custom template tag:
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" %}
{% settings_value "DATABASES" %}
?这个用例应该清楚地说明为什么设置在模板中不可用。
templatetags
文件夹,其中包含一个空的 __init__.py
文件,并且该文件夹内的此代码为 settings.py
。 2)在您的模板中添加 {% load settings %}
,然后使用您的新标签!
如果您使用 django 的内置通用视图或在 render_to_response
快捷函数中传入上下文实例关键字参数,Django 提供对模板的某些常用设置常量的访问,例如 settings.MEDIA_URL
和一些语言设置。以下是每种情况的示例:
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)
现在您可以在模板上以 {{ favorite_color }}
的身份访问 settings.FAVORITE_COLOR
。
django-settings-export
以避免在每个视图中都编写此代码。
查看 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>
render
而不是 render_to_response
另一种方法是创建一个自定义模板标签,它可以让您从设置中提取值。
@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" %}
将其打印在任何页面上,而无需跳过上下文处理器箍。
templatetags
的新文件夹,其中包含空的 __init__.py
。然后,使用上面的代码创建一个 custom_tags.py
(不要忘记 register = template.Library()
。其次,在 INSTALLED_APPS = [..., 'your_app.templatetags', ..]
中注册。第三,在 html-template 标头中,您需要加载模块:{% load custom_tags %}
。然后它将工作:{% value_from_settings "A_PARAMETER_FROM_SETTINGS" %}
我喜欢 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 的原创想法!
if name in ALLOWABLE_VALUES: ...
'val' in ('val_first', 'second_val',)
是 False
,这里没有子字符串问题。
if
语句中使用它?我想检查 DEBUG
值
使用 Django 2.0+ 添加包含创建自定义模板标签的完整说明的答案以解决此问题
在您的应用程序文件夹中,创建一个名为 templatetags 的文件夹。在其中创建 __init__.py 和 custom_tags.py:
https://i.stack.imgur.com/P9AXj.png
在 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 文档中的 the section on simple tags。
然后,您需要通过将这个文件加载到您将使用它的任何模板中来让 Django 知道这个(以及任何附加的)自定义标签。就像您需要加载内置的静态标签一样:
{% load custom_tags %}
加载后,它可以像任何其他标签一样使用,只需提供您需要返回的特定设置。因此,如果您的设置中有 BUILD_VERSION 变量:
{% get_setting "BUILD_VERSION" %}
此解决方案不适用于数组,但如果您需要,您可能会在模板中添加大量逻辑。
注意:一个更干净和故障安全的解决方案可能是制作一个自定义上下文处理器,您可以在其中将所需的设置添加到所有模板都可用的上下文中。这样,您就可以降低在模板中错误地输出敏感设置的风险。
将此代码添加到名为 context_processors.py
的文件中:
from django.conf import settings as django_settings
def settings(request):
return {
'settings': django_settings,
}
然后,在您的设置文件中,在 TEMPLATES
的 'context_processors'
设置中包含一个路径,例如 'speedy.core.base.context_processors.settings'
(带有您的应用程序名称和路径)。
(您可以看到例如 settings/base.py 和 context_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,
}
SECRET_KEY
。黑客可能会滥用此功能在模板中显示此类信息。
TEMPLATES.OPTIONS.context_processors
部分:{2 } 或更一般的 '[APP_NAME].context_processors.settings'
,其中 [APP_NAME] 应替换为您的应用程序的名称。
我稍微改进了 chrisdew's answer(创建您自己的标签)。
首先,创建文件 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 ...
表示法的优点在于,它可以通过简单的 {{my_fqdn}}
在 blocktrans
块中轻松使用。
如果使用基于类的视图:
#
# 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 }}
上面来自 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',
...
)
如果有人像我一样发现这个问题,那么我将发布适用于 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/
{% if settings_debug %}
{% if settings_debug == True %}
更改为您建议的 {% if settings_debug %}
我发现这是 Django 1.3 最简单的方法:
views.py from local_settings import BASE_URL def root(request): return render_to_response('hero.html', {'BASE_URL': BASE_URL}) hero.html var BASE_URL = '{{ JS_BASE_URL }}';
对于那些想要使用带有 if
标签的@Berislav 的方法(自定义模板标签)的人:
/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 %}
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")
如果我们要比较单个变量上的上下文和模板标签,那么了解更有效的选项可能是有益的。但是,您最好只从需要该变量的模板中深入了解设置。在这种情况下,将变量传递给所有模板是没有意义的。但是,如果您将变量发送到通用模板(例如 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)
SITE_EXTRA_CONTEXT_DICT
为您完成。
更完整的实现。
/project/settings.py
APP_NAME = 'APP'
/app/templatetags/settings_value.py
from django import template
from django.conf import settings
register = template.Library()
@register.simple_tag
def settings_value(name):
return getattr(settings, name, "")
/app/templates/index.html
<!DOCTYPE html>
{% load static %}
{% load settings_value %}
<head>
<title>{% settings_value "APP_NAME" %}</title>
...
context_process.py
放在我的settings.py
文件旁边,并将"context_processors.admin_media"
添加到我的TEMPLATE_CONTEXT_PROCESSORS
列表中。此外,您可能希望在答案中添加一条注释,说明 TEMPLATE_CONTEXT_PROCESSORS 的默认值不为空,因此如果任何现有代码使用这些默认上下文处理器设置的任何值,除非您将它们添加回来,否则它们将不起作用明确地列出来。render
快捷方式来避免显式包含 RequestContext:docs.djangoproject.com/en/1.6/topics/http/shortcuts/#render