我有一些东西在设置。py,我想能够从模板访问,但我不知道如何做到这一点。我已经试过了
{{CONSTANT_NAME}}
但这似乎并不奏效。这可能吗?
我有一些东西在设置。py,我想能够从模板访问,但我不知道如何做到这一点。我已经试过了
{{CONSTANT_NAME}}
但这似乎并不奏效。这可能吗?
如果你希望每个请求和模板都有一个值,那么使用上下文处理器更合适。
方法如下:
Make a context_processors.py file in your app directory. Let's say I want to have the ADMIN_PREFIX_VALUE value in every context: 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} add your context processor to your settings.py file: TEMPLATES = [{ # whatever comes before 'OPTIONS': { 'context_processors': [ # whatever comes before "your_app.context_processors.admin_media", ], } }] Use RequestContext in your view to add your context processors in your template. The render shortcut does this automatically: from django.shortcuts import render def my_view(request): return render(request, "index.html") and finally, in your template: ... <a href="{{ ADMIN_MEDIA_URL }}">path to admin media</a> ...
Django提供了对模板中某些常用的设置常量的访问,比如settings。MEDIA_URL和一些语言设置,如果你使用django内置的通用视图或在render_to_response快捷函数中传入context实例关键字参数。以下是每种情况的示例:
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}}。
另一种方法是创建一个自定义模板标签,它可以让您从设置中获取值。
@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" %}
将它打印在任何页面上,而无需跳过上下文处理器的约束。
上面来自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',
...
)
我稍微改进了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的优点是…这使得它很容易通过一个简单的{{my_fqdn}}在blocktrans块中使用。
我发现最简单的方法是一个自定义模板标签:
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" %}
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")
If we were to compare context vs. template tags on a single variable, then knowing the more efficient option could be benificial. However, you might be better off to dip into the settings only from templates that need that variable. In that case it doesn't make sense to pass the variable into all templates. But if you are sending the variable into a common template such as the base.html template, Then it would not matter as the base.html template is rendered on every request, so you can use either methods.
如果您决定使用template tags选项,那么使用下面的代码,因为它允许您传入一个默认值,以防有问题的变量未定义。
例如: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)
如果使用基于类的视图:
#
# 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 }}
我发现这是Django 1.3最简单的方法:
views.py 从local_settings导入BASE_URL def根(请求): 返回render_to_response('hero.html', {'BASE_URL': BASE_URL}) hero.html var BASE_URL = '{{JS_BASE_URL}}';
我喜欢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" %}
This protects any constants that you have not named from use in the template, and if you wanted to get really fancy, you could set a tuple in the settings, and create more than one template tag for different pages, apps or areas, and simply combine a local tuple with the settings tuple as needed, then do the list comprehension to see if the value is acceptable. I agree, on a complex site, this is a bit simplistic, but there are values that would be nice to have universally in templates, and this seems to work nicely. Thanks to Berislav for the original idea!
查看django-settings-export(免责声明:我是这个项目的作者)。
例如……
$ pip install django-settings-export
settings.py
TEMPLATES = [
{
'OPTIONS': {
'context_processors': [
'django_settings_export.settings_export',
],
},
},
]
MY_CHEESE = 'Camembert';
SETTINGS_EXPORT = [
'MY_CHEESE',
]
template.html
<script>var MY_CHEESE = '{{ settings.MY_CHEESE }}';</script>
如果有人像我一样发现了这个问题,那么我将发布我的解决方案,它适用于Django 2.0:
这个标记将一些settings.py变量值赋给模板的变量:
用法:{% get_settings_value template_var "SETTINGS_VAR" %}
应用程序/ templatetags / 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/
在Django 2.0+中添加了一个完整的创建自定义模板标签的答案
在你的app文件夹中,创建一个名为templatetags的文件夹。在其中,创建__init__.py和custom_tags.py:
在custom_tags.py中创建一个自定义标记函数,用于访问settings常量中的任意键:
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" %}
此解决方案不适用于数组,但如果需要,则可能需要在模板中放入太多逻辑。
注意:一个更清晰、更安全的解决方案可能是创建一个自定义上下文处理器,在其中添加所有模板可用的上下文所需的设置。这样可以降低在模板中错误地输出敏感设置的风险。
将这段代码添加到名为context_processors.py的文件中:
from django.conf import settings as django_settings
def settings(request):
return {
'settings': django_settings,
}
然后,在你的设置文件中,包括一个路径,如'speed .core.base.context_processors。在TEMPLATES中的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,
}
对于那些想要使用@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 %}
一个更完整的实现。
/项目/ 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>
...