У налаштуваннях.py є деякі речі, до яких я хотів би отримати доступ із шаблону, але не можу зрозуміти, як це зробити. Я вже пробував
{{CONSTANT_NAME}}
але це, здається, не працює. Чи можливо це?
У налаштуваннях.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
Я вважаю найпростішим підходом єдиний тег шаблону :
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>
render
а неrender_to_response
Інший спосіб зробити це - створити спеціальний тег шаблону, який дозволяє виводити значення з налаштувань.
@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+
У своїй папці додатків створіть папку під назвою теги шаблонів . У ньому створіть __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.
Тоді вам потрібно повідомити Джанго про цей (та будь-який додатковий) спеціальний тег, завантаживши цей файл у будь-який шаблон, де ви його будете використовувати. Як і вам потрібно завантажити вбудований статичний тег:
{% 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
.
(Ви можете побачити, наприклад, налаштування / 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 як 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)
SITE_EXTRA_CONTEXT_DICT
в кінцевому посуді, щоб зробити це за вас.