Can I access constants in settings.py from templates in Django?
我在settings.py中有一些东西,我希望能够从模板访问,但我无法弄清楚如何做到这一点。 我已经试过了
1 | {{CONSTANT_NAME}} |
但这似乎不起作用。 这可能吗?
如果它是您想要的每个请求和价值的值。模板,使用上下文处理器更合适。
这是如何做:
在app目录中创建一个
1 2 3 4 5 | 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} |
将您的上下文处理器添加到settings.py文件中:
1 2 3 4 5 6 7 8 9 | TEMPLATES = [{ # whatever comes before 'OPTIONS': { 'context_processors': [ # whatever comes before "your_app.context_processors.admin_media", ], } }] |
在视图中使用
1 2 3 4 | from django.shortcuts import render def my_view(request): return render(request,"index.html") |
最后,在你的模板中:
1 2 3 | ... path to admin media ... |
我发现最简单的方法是单个模板标记:
1 2 3 4 5 6 7 8 9 | 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,"") |
用法:
1 | {% settings_value"LANGUAGE_CODE" %} |
如果您使用django内置的通用视图或在
1 2 3 4 5 6 7 8 9 | 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)) |
这些视图都有几个常用的设置,如
如果您正在寻找设置中其他常量的访问权限,那么只需解压缩您想要的常量并将它们添加到您在视图函数中使用的上下文字典中,如下所示:
1 2 3 4 5 6 | 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) |
现在,您可以在
查看
例如...
1 | $ pip install django-settings-export |
settings.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | TEMPLATES = [ { 'OPTIONS': { 'context_processors': [ 'django_settings_export.settings_export', ], }, }, ] MY_CHEESE = 'Camembert'; SETTINGS_EXPORT = [ 'MY_CHEESE', ] |
template.html
1 | var MY_CHEESE = '{{ settings.MY_CHEESE }}'; |
另一种方法是创建一个自定义模板标记,它可以让您从设置中捕获值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @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)) |
然后你可以使用:
1 | {% value_from_settings"FQDN" %} |
在任何页面上打印它,而不跳过上下文处理器箍。
我喜欢Berislav的解决方案,因为在简单的网站上,它是干净而有效的。我不喜欢的是无所不在地暴露所有设置常量。所以我最终做的是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 '' |
用法:
1 | {% settings_value"CONSTANT_NAME_1" %} |
这可以保护您未在模板中使用的任何常量,如果您想真正了解,可以在设置中设置元组,并为不同的页面,应用或区域创建多个模板标记,并简单地根据需要将本地元组与设置元组组合,然后执行列表推导以查看该值是否可接受。
我同意,在一个复杂的网站上,这有点过于简单,但有一些值很高兴在模板中普遍使用,这看起来效果很好。
感谢Berislav最初的想法!
我改进了chrisdew的答案(创建你自己的标签)。
首先,创建文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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 |
您可以通过以下方式在模板中使用此标记:
1 2 3 | {% load value_from_settings %} [...] {% value_from_settings"FQDN" %} |
或通过
1 2 3 | {% load value_from_settings %} [...] {% value_from_settings"FQDN" as my_fqdn %} |
使用Django 2.0+添加一个答案,其中包含创建解决此问题的自定义模板标记的完整说明
在您的app-folder中,创建一个名为templatetags的文件夹。在其中,创建__init__.py和custom_tags.py:
在custom_tags.py中创建一个自定义标记函数,该函数提供对设置常量中任意键的访问:
1 2 3 4 5 6 7 8 | 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知道此(以及任何其他)自定义标记。就像你需要加载内置静态标记一样:
1 | {% load custom_tags %} |
加载后,它可以像任何其他标签一样使用,只需提供您需要返回的特定设置。因此,如果您的设置中有BUILD_VERSION变量:
1 | {% get_setting"BUILD_VERSION" %} |
此解决方案不适用于数组,但如果您需要,您可能会在模板中添加许多逻辑。
bchhun上面的例子很好,除了你需要从settings.py显式构建你的上下文字典。下面是一个UNTESTED示例,说明如何从settings.py的所有大写属性自动构建上下文字典(re:"^ [A-Z0-9 _] + $")。
在settings.py结束时:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | _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变量值分配给模板的变量:
用法:
应用程序/ templatetags / my_custom_tags.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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) |
你的模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | {% 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/
将此代码添加到名为
1 2 3 4 5 6 7 | from django.conf import settings as django_settings def settings(request): return { 'settings': django_settings, } |
然后,在您的设置文件中,在
(你可以看看例如https://github.com/speedy-net/speedy-net/blob/staging/speedy/core/settings/base.py和https://github.com/speedy-net/speedy-净/斑点/分段/迅速/型芯/碱/ context_processors.py)。
如果使用基于类的视图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # # 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
1 2 3 4 | from local_settings import BASE_URL def root(request): return render_to_response('hero.html', {'BASE_URL': BASE_URL}) |
hero.html
1 | var BASE_URL = '{{ JS_BASE_URL }}'; |
如果我们要在单个变量上比较上下文与模板标签,那么了解更有效的选项可能是有益的。但是,您最好只从需要该变量的模板中进入设置。在这种情况下,将变量传递到所有模板中是没有意义的。但是,如果您要将变量发送到公共模板(例如base.html模板),那么随着base.html模板在每个请求上呈现都无关紧要,因此您可以使用任一方法。
如果您决定使用模板标签选项,则使用以下代码,因为它允许您传入默认值,以防未定义变量问题。
示例:get_from_settings my_variable为my_context_value
示例:get_from_settings my_variable my_default as my_context_value
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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) |
IanSR和bchhun都建议在设置中覆盖TEMPLATE_CONTEXT_PROCESSORS。请注意,如果您在不重新设置默认值的情况下覆盖它,则此设置有一个默认设置可能会导致一些棘手的事情。在最近的Django版本中,默认值也发生了变化。
https://docs.djangoproject.com/en/1.3/ref/settings/#template-context-processors
默认TEMPLATE_CONTEXT_PROCESSORS:
1 2 3 4 5 6 | 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") |