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

Pau*_*cks 346 django django-templates django-settings

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

{{CONSTANT_NAME}}
Run Code Online (Sandbox Code Playgroud)

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

bch*_*hun 416

如果它是您希望为每个请求和模板提供的值,则使用上下文处理器更合适.

这是如何做:

  1. context_processors.py在您的app目录中创建一个文件.假设我想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}
    
    Run Code Online (Sandbox Code Playgroud)
  2. 将您的上下文处理器添加到settings.py文件中:

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

    from django.shortcuts import render
    
    def my_view(request):
        return render(request, "index.html")
    
    Run Code Online (Sandbox Code Playgroud)
  4. 最后,在你的模板中:

    ...
    <a href="{{ ADMIN_MEDIA_URL }}">path to admin media</a>
    ...
    
    Run Code Online (Sandbox Code Playgroud)

  • 这看起来很痛苦.为什么这么多箍要抓一个变量? (54认同)
  • @MarkEssel这些箍是这样生成的,因此只要它使用RequestContext函数,就可以在每个View中访问变量.您始终可以在每个视图中手动获取设置变量.我会随时选择一个可重复使用的Context Processor而不是'复制和粘贴'. (32认同)
  • @bchhun我刚刚测试过(Django 1.3):在应用程序之间共享上下文处理器工作正常.:-)我把`context_process.py`放在我的`settings.py`文件旁边,并将``context_processors.admin_media``添加到我的`TEMPLATE_CONTEXT_PROCESSORS`列表中.此外,您可能希望在答案中添加一条关于TEMPLATE_CONTEXT_PROCESSORS的默认值不为空的说明,因此如果任何现有代码使用这些默认上下文处理器设置的任何值,除非您将它们添加回来,否则它们将无法工作到列表明确. (10认同)
  • 尽力避免在任何地方复制/粘贴.每个应用程序(在一个项目中)是否需要一个context_processor.py,有没有办法为它们构建一个context_processor? (5认同)
  • @MarkEssel一点也不痛苦 - 他只是拼出一切.它实际上只有6条短线(第1步和第2步).无论如何,大多数模板都需要步骤3和4或它们的等效物. (5认同)
  • 从Django 1.3开始,您可以使用`render`快捷方式来避免显式包含RequestContext:https://docs.djangoproject.com/en/1.6/topics/http/shortcuts/#render (2认同)

Ber*_*pac 248

我发现最简单的方法是单个模板标记:

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, "")
Run Code Online (Sandbox Code Playgroud)

用法:

{% settings_value "LANGUAGE_CODE" %}
Run Code Online (Sandbox Code Playgroud)

  • "我们都在这里同意成年人" (21认同)
  • 我喜欢按需访问模板中的任何设置,这提供了优雅.如果您经常在模板中使用各种设置,这比其他答案要好得多:1)接受的答案与基于类的视图不兼容或笨拙.2)使用过度投票的模板上下文处理器解决方案,您必须指定单个设置(或全部),并且它将针对呈现模板的每个请求运行 - 效率低下!3)它比上面更复杂的标签更简单. (16认同)
  • @BenRoberts我同意这是一个优雅的解决方案......但仅适用于只有一个开发人员完成所有事情的小项目.如果您有单独的人员/团队进行设计和开发,那么这个解决方案可能是最糟糕的**.什么阻止设计师滥用这个标签:`{%settings_value"DATABASES"%}`?这个用例应该很清楚为什么设置在模板中不可用. (15认同)
  • 请原谅我是个新手.你把这个代码放在哪里?Views.py?或者在新文件上? (11认同)
  • 为了让其他人清楚,你需要:1)在你的应用程序中创建一个`templatetags`文件夹,其中包含一个空的`__init __.py`文件,该代码作为该文件夹中的`settings.py`.2)在你的模板中添加`{%load settings%}`然后使用你的新标签! (11认同)
  • 那么你总是可以扩展我的例子,包括你允许以这种方式调用的设置列表; 如果一个人调用一个不公开的字符串,只需返回一个简单的空字符串. (9认同)
  • 如果你需要一个'if`就可以了?你怎么能用它? (2认同)

Pra*_*ogg 169

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))
Run Code Online (Sandbox Code Playgroud)

这些视图都有几个常用的设置,如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)
Run Code Online (Sandbox Code Playgroud)

现在,您可以settings.FAVORITE_COLOR在模板上访问{{ favorite_color }}.

  • 值得注意的是,使用RequestContext添加的特定值取决于TEMPLATE_CONTEXT_PROCESSORS的值.因此,如果您希望在任何地方传递其他值,只需编写自己的上下文处理器并将其添加到TEMPLATE_CONTEXT_PROCESSORS. (65认同)
  • 请查看[`django-settings-export`](https://github.com/jakubroztocil/django-settings-export),以避免在每个视图中编写此代码. (14认同)

Jak*_*cil 90

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

例如...

$ pip install django-settings-export
Run Code Online (Sandbox Code Playgroud)

settings.py

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

MY_CHEESE = 'Camembert';

SETTINGS_EXPORT = [
    'MY_CHEESE',
]
Run Code Online (Sandbox Code Playgroud)

template.html

<script>var MY_CHEESE = '{{ settings.MY_CHEESE }}';</script>
Run Code Online (Sandbox Code Playgroud)

  • 现在是2019年,我正在项目中使用它。谢谢! (3认同)
  • 我同意@sivabudh。这对我来说也是最好的解决方案,因为 1. 它是集中式的,这意味着我不需要额外的文件夹和文件,2. 我可以在模板中看到设置命名空间,这对于获取许多应用程序的引用非常有帮助。 (2认同)

fad*_*bee 43

另一种方法是创建一个自定义模板标记,它可以让您从设置中捕获值.

@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))
Run Code Online (Sandbox Code Playgroud)

然后你可以使用:

{% value_from_settings "FQDN" %}
Run Code Online (Sandbox Code Playgroud)

在任何页面上打印它,而不跳过上下文处理器箍.

  • 我认为这是最优雅的解决方案,因为它可以在不改变代码的情况下作为dropin工作. (6认同)
  • @ register.tag代码驻留在哪个文件中? (3认同)
  • @Mark - 在produi/src/produi/template_utils/templatetags/custom_template_filters.py template_utils中引用settings.py INSTALLED_APPS - 另见https://docs.djangoproject.com/en/dev/howto/custom-template-tags/ (2认同)
  • 我花了一些时间让事情按照这个答案中的建议正常工作...首先,您需要在应用程序的文件夹中创建一个名为“templatetags”的新文件夹,其中包含空的“__init__.py”。然后,使用上面的代码创建一个 `custom_tags.py` (不要忘记 `register = template.Library()`。其次,在 `INSTALLED_APPS = [..., 'your_app.templatetags', ..] 中注册`。第三,在 html 模板标头中,您需要加载模块:`{% load custom_tags %}`。然后它将起作用:`{% value_from_settings "A_PARAMETER_FROM_SETTINGS" %}` (2认同)

Mon*_*ard 25

我喜欢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 ''
Run Code Online (Sandbox Code Playgroud)

用法:

{% settings_value "CONSTANT_NAME_1" %}
Run Code Online (Sandbox Code Playgroud)

这可以保护您未在模板中使用的任何常量,如果您想真正了解,可以在设置中设置元组,并为不同的页面,应用或区域创建多个模板标记,并简单地根据需要将本地元组与设置元组组合,然后执行列表推导以查看该值是否可接受.
我同意,在一个复杂的网站上,这有点过于简单,但有一些值很高兴在模板中普遍使用,这看起来效果很好.感谢Berislav最初的想法!

  • 为什么不简单`如果名字在ALLOWABLE_VALUES:...` (5认同)
  • 只是为了澄清任何想知道的人:''val'in('val_first','second_val',)`是'False`,这里没有子串问题. (5认同)
  • 我该如何在`if`语句中使用它?我想检查`DEBUG`的值 (2认同)

pkl*_*aus 11

我改进了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
Run Code Online (Sandbox Code Playgroud)

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

{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" %}
Run Code Online (Sandbox Code Playgroud)

或通过

{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" as my_fqdn %}
Run Code Online (Sandbox Code Playgroud)

这种as ...符号的优点在于,blocktrans通过简单的方法可以很容易地在块中使用{{my_fqdn}}.


And*_*röm 10

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

在您的应用程序文件夹中,创建一个名为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, "")
Run Code Online (Sandbox Code Playgroud)

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

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

{% load custom_tags %}
Run Code Online (Sandbox Code Playgroud)

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

{% get_setting "BUILD_VERSION" %}
Run Code Online (Sandbox Code Playgroud)

此解决方案不适用于数组,但是如果需要,可以在模板中增加很多逻辑。


Bil*_*zke 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 }}
Run Code Online (Sandbox Code Playgroud)


Ian*_*nSR 7

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',
...
)
Run Code Online (Sandbox Code Playgroud)


Nul*_*ot0 6

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

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

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

app / 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)
Run Code Online (Sandbox Code Playgroud)

您的模板:

{% 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 %}
Run Code Online (Sandbox Code Playgroud)

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


Uri*_*Uri 5

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

from django.conf import settings as django_settings


def settings(request):
    return {
        'settings': django_settings,
    }
Run Code Online (Sandbox Code Playgroud)

然后,在你的设置文件,包括路径,例如'speedy.core.base.context_processors.settings'(与你的应用程序名称和路径)中'context_processors'的设置TEMPLATES

(例如,您可以查看https://github.com/speedy-net/speedy-net/blob/staging/speedy/core/settings/base.pyhttps://github.com/speedy-net/speedy- net / blob / staging / speedy / core / base / context_processors.py)。

  • 我昨天遇到了这个问题,找到了这篇文章,然后是另外 2 篇文章和一篇博客文章,我觉得每一篇都过于复杂(不幸的是,我没有把它放在页面下面这么远,真丢脸)。所以我最终推出了自己的解决方案,这正是这个解决方案。我刚回来是因为当这个^^^ 3行函数和settings.py中的1行更改时,人们推荐插件和一大堆代码,这让我很烦恼。 (2认同)

小智 5

对于那些想要使用 @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, "")
Run Code Online (Sandbox Code Playgroud)

模板文件:

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

{% if ENABLE_FEATURE_A %}
<!-- Feature A stuffs -->
{% endif %}
Run Code Online (Sandbox Code Playgroud)