Могу ли я получить доступ к константам в settings.py из шаблонов в Django? - PullRequest
337 голосов
/ 11 января 2009

У меня есть некоторые вещи в settings.py, к которым я хотел бы получить доступ из шаблона, но я не могу понять, как это сделать. Я уже попробовал

{{CONSTANT_NAME}}

но это не похоже на работу. Возможно ли это?

Ответы [ 15 ]

401 голосов
/ 11 января 2009

Если это значение, которое вы хотели бы иметь для каждого запроса и шаблона, лучше использовать контекстный процессор .

Вот как:

  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>
    ...
    
236 голосов
/ 10 октября 2011

Я считаю, что самым простым подходом является использование одного тега шаблона:

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" %}
164 голосов
/ 11 января 2009

Django предоставляет доступ к некоторым часто используемым константам настроек шаблона, таким как settings.MEDIA_URL и некоторые языковые настройки, если вы используете встроенные общие представления django или передаете аргумент ключевого слова экземпляра контекста в ярлыке render_to_response функция. Вот пример каждого случая:

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)

Теперь вы можете получить доступ к settings.FAVORITE_COLOR в вашем шаблоне как {{ favorite_color }}.

88 голосов
/ 15 сентября 2014

Проверить 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>
42 голосов
/ 08 марта 2011

Еще один способ сделать это - создать собственный тег шаблона, который позволит вам вывести значения из настроек.

@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" %}

чтобы распечатать его на любой странице, не перепрыгивая через контекстные процессоры.

24 голосов
/ 06 февраля 2014

Мне нравится решение Берислава, потому что на простых сайтах оно чисто и эффективно. Что мне НЕ нравится, так это выставление всех констант настроек волей-неволей. Итак, что я в итоге сделал, это:

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" %}

Это защищает любые константы, которые вы не назвали, от использования в шаблоне, и, если вы хотите получить действительно модный, вы можете установить кортеж в настройках и создать более одного тега шаблона для разных страниц, приложений или областей и просто объедините локальный кортеж с кортежем настроек по мере необходимости, затем выполните понимание списка, чтобы увидеть, является ли значение приемлемым.
Я согласен, на сложном сайте это немного упрощенно, но есть значения, которые было бы неплохо иметь универсально в шаблонах, и это, кажется, работает хорошо. Спасибо Бериславу за оригинальную идею!

11 голосов
/ 14 июня 2011

Я немного улучшил ответ 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 ... состоит в том, что это облегчает использование в blocktrans блоках с помощью простого {{my_fqdn}}.

8 голосов
/ 25 апреля 2018

Добавление ответа с полными инструкциями для создания пользовательского тега шаблона, который решает эту проблему, с помощью Django 2.0 +

В вашей папке приложения создайте папку с именем templatetags . В нем создайте __ init __. Py и custom_tags.py :

Custom tags folder structure

В 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 документах.

Затем вам нужно сообщить Django об этом (и любом дополнительном) пользовательском теге, загрузив этот файл в любой шаблон, в котором вы будете его использовать. Так же, как вам нужно загрузить встроенный статический тег:

{% load custom_tags %}

Когда он загружен, его можно использовать, как и любой другой тег, просто укажите нужные вам настройки. Так что если в ваших настройках есть переменная BUILD_VERSION:

{% get_setting "BUILD_VERSION" %}

Это решение не будет работать с массивами, но, если вам это нужно, вы можете использовать большую логику в своих шаблонах.

7 голосов
/ 28 марта 2011

Пример выше от 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',
...
)
5 голосов
/ 17 января 2018

Если кто-то найдет этот вопрос, как я, то я выложу свое решение, которое работает на 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/

...