Могу ли я получить доступ к константам в settings.py из шаблонов в Django?



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

но это, похоже, не работает. Это возможно?




Если бы мы сравнивали теги контекста и шаблона с одной переменной, то знание более эффективного варианта могло бы быть benificial. Однако вам может быть лучше окунуться в настройки только из шаблонов, которые нуждаются в этой переменной. В этом случае нет смысла передавать переменную во все шаблоны. Но если вы отправляете переменную в общий шаблон, такой как шаблон base.html, то это не имеет значения, поскольку шаблон base.html отображается по каждому запросу, поэтому вы можете использовать оба метода.

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

Пример: get_from_settings my_variable как my_context_value

Пример: get_from_settings my_variable my_default как 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)



Проверьте 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>



Как 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")



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

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

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




Приведенный выше пример из 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',
...
)



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




Links