У меня есть некоторые вещи в settings.py, к которым я хотел бы получить доступ из шаблона, но я не могу понять, как это сделать. Я уже пробовала
{{CONSTANT_NAME}}
но это не похоже на работу. Это возможно?
У меня есть некоторые вещи в settings.py, к которым я хотел бы получить доступ из шаблона, но я не могу понять, как это сделать. Я уже пробовала
{{CONSTANT_NAME}}
но это не похоже на работу. Это возможно?
Ответы:
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 }}
.
django-settings-export
чтобы избежать необходимости писать этот код в каждом представлении.
Если это значение, которое вы хотели бы иметь для каждого запроса и шаблона, лучше использовать контекстный процессор .
Вот как:
Создайте 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}
добавьте ваш контекстный процессор в ваш файл settings.py :
TEMPLATES = [{
# whatever comes before
'OPTIONS': {
'context_processors': [
# whatever comes before
"your_app.context_processors.admin_media",
],
}
}]
Используйте RequestContext
в вашем представлении, чтобы добавить ваши контекстные процессоры в ваш шаблон. render
Ярлык делает это автоматически:
from django.shortcuts import render
def my_view(request):
return render(request, "index.html")
и, наконец, в вашем шаблоне:
...
<a href="{{ ADMIN_MEDIA_URL }}">path to admin media</a>
...
context_process.py
рядом с моим settings.py
файлом и добавил "context_processors.admin_media"
в свой TEMPLATE_CONTEXT_PROCESSORS
список. Кроме того, вы можете добавить примечание в своем ответе о том факте, что значение по умолчанию TEMPLATE_CONTEXT_PROCESSORS не является пустым, поэтому, если какой-либо из существующих кодов использует любое из значений, установленных этими процессорами контекста по умолчанию, они не будут работать, если вы не добавите их обратно. в список явно.
render
ярлык, чтобы избежать необходимости явно включать RequestContext: docs.djangoproject.com/en/1.6/topics/http/shortcuts/#render
Я считаю, что самым простым подходом является использование одного пользовательского тега шаблона :
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" %}
{% settings_value "DATABASES" %}
:? Этот вариант использования должен прояснить, почему настройки не доступны в шаблонах для начала.
templatetags
папку внутри вашего приложения с пустым __init__.py
файлом и этим кодом, как settings.py
внутри этой папки. 2) в свой шаблон вы добавляете {% load settings %}
и затем используете свой новый тег!
Проверьте django-settings-export
(отказ от ответственности: я автор этого проекта).
Например...
$ pip install django-settings-export
TEMPLATES = [
{
'OPTIONS': {
'context_processors': [
'django_settings_export.settings_export',
],
},
},
]
MY_CHEESE = 'Camembert';
SETTINGS_EXPORT = [
'MY_CHEESE',
]
<script>var MY_CHEESE = '{{ settings.MY_CHEESE }}';</script>
Еще один способ сделать это - создать пользовательский тег шаблона, который позволит вам вывести значения из настроек.
@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" %}
распечатать его на любой странице, не перепрыгивая через контекстные процессоры.
Мне нравится решение Берислава, потому что на простых сайтах оно чисто и эффективно. Что мне НЕ нравится, так это выставление всех констант настроек волей-неволей. Итак, что я в итоге сделал это:
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" %}
Это защищает любые константы, которые вы не назвали, от использования в шаблоне, и, если вы хотите получить действительно модный, вы можете установить кортеж в настройках и создать более одного тега шаблона для разных страниц, приложений или областей, и просто при необходимости объедините локальный кортеж с кортежем настроек, затем выполните понимание списка, чтобы увидеть, является ли значение приемлемым.
Я согласен, на сложном сайте это немного упрощенно, но есть значения, которые было бы неплохо иметь универсально в шаблонах, и это, кажется, работает хорошо. Спасибо Бериславу за оригинальную идею!
if name in ALLOWABLE_VALUES: ...
'val' in ('val_first', 'second_val',)
это False
, не подстрок проблемы.
if
заявлении? Я хочу проверить DEBUG
значение
Я немного улучшил ответ 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}}
.
Добавление ответа с подробными инструкциями по созданию настраиваемого тега шаблона, решающего эту проблему, с помощью Django 2.0+
В вашей папке приложения создайте папку с именем templatetags . В нем создайте __init__.py и custom_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, "")
Чтобы понять этот код, я рекомендую прочитать раздел о простых тегах в документации Django.
Затем вам нужно сообщить Django об этом (и любом дополнительном) пользовательском теге, загрузив этот файл в любой шаблон, где вы будете его использовать. Так же, как вам нужно загрузить встроенный статический тег:
{% load custom_tags %}
Когда он загружен, его можно использовать так же, как и любой другой тег, просто укажите нужную настройку, которую вам нужно вернуть. Так что если у вас есть переменная BUILD_VERSION в ваших настройках:
{% get_setting "BUILD_VERSION" %}
Это решение не будет работать с массивами, но, если вам это нужно, вы можете использовать большую логику в своих шаблонах.
Примечание. Более чистым и отказоустойчивым решением, вероятно, было бы создание настраиваемого контекстного процессора, в котором вы добавляете нужные настройки в контекст, доступный для всех шаблонов. Таким образом, вы по ошибке уменьшите риск вывода конфиденциальных настроек в ваши шаблоны.
Добавьте этот код в файл с именем context_processors.py
:
from django.conf import settings as django_settings
def settings(request):
return {
'settings': django_settings,
}
А затем, в вашем файле настроек, включите путь, такой как 'speedy.core.base.context_processors.settings'
(с вашим именем приложения и пути) в 'context_processors'
настройках в TEMPLATES
.
(Вы можете увидеть, например, settings / base.py и context_processors.py ).
Затем вы можете использовать определенные настройки в любом коде шаблона. Например:
{% if settings.SITE_ID == settings.SPEEDY_MATCH_SITE_ID %}
Обновление: приведенный выше код предоставляет все настройки для шаблонов, включая конфиденциальную информацию, такую как ваша SECRET_KEY
. Хакер может использовать эту функцию для отображения такой информации в шаблонах. Если вы хотите предоставить шаблонам только определенные настройки, используйте этот код:
def settings(request):
settings_in_templates = {}
for attr in ["SITE_ID", ...]: # Write here the settings you want to expose to the templates.
if (hasattr(django_settings, attr)):
settings_in_templates[attr] = getattr(django_settings, attr)
return {
'settings': settings_in_templates,
}
SECRET_KEY
. Хакер может использовать эту функцию для отображения такой информации в шаблонах.
Приведенный выше пример из 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',
...
)
Если кто-то найдет этот вопрос, как я, я опубликую свое решение, которое работает на Django 2.0:
Этот тег назначает некоторое значение переменной settings.py переменной шаблона:
Применение: {% get_settings_value template_var "SETTINGS_VAR" %}
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/
{% if settings_debug %}
{% if settings_debug == True %}
на предложенное{% if settings_debug %}
Если используется представление на основе классов:
#
# 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 }}
И 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")
Если бы мы сравнили теги контекста и шаблона на одной переменной, то знание более эффективного варианта могло бы принести пользу. Тем не менее, вам может быть лучше окунуться в настройки только из шаблонов, которые нуждаются в этой переменной. В этом случае нет смысла передавать переменную во все шаблоны. Но если вы отправляете переменную в общий шаблон, такой как шаблон 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)
SITE_EXTRA_CONTEXT_DICT
в Finalware, чтобы сделать это для вас.