我可以通过Django中的模板访问settings.py中的常量吗?


6 Answers

如果这是您想要的每个请求和模板的值,则使用上下文处理器更合适。

就是这样:

  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>
    ...
    
Question

我在settings.py中有一些我希望能够从模板访问的东西,但我无法弄清楚如何去做。 我已经尝试过了

{{CONSTANT_NAME}}

但这似乎并不奏效。 这可能吗?




退房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>



从bchhun上面的例子很好,除了你需要显式地从settings.py构建你的上下文字典。 下面是一个UNTESTED示例,说明如何从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',
...
)



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")



我喜欢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提出的最初创意!




如果有人像我这样发现了这个问题,那么我会发布我的解决方案,它在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 == True %}
... do something ...
{% else %}
... do other stuff ...
{% endif %}

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




如果我们要在单个变量上比较上下文和模板标签,那么知道更高效的选项可能是非常有效的。 但是,您最好只能从需要该变量的模板中进入设置。 在这种情况下,将变量传递到所有模板是没有意义的。 但是,如果您要将变量发送到通用模板(如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)



Related