14 ответов:
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 }}.
если это значение, которое вы хотели бы иметь для каждого запроса и шаблона, используя контекст процессора более уместен.
вот так:
сделать
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 file:
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> ...
Я считаю, что самый простой подход - это один тег шаблона:
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" %}
проверить
django-settings-export(отказ от ответственности: я автор этого проекта).например...
$ pip install django-settings-exportsettings.py
TEMPLATES = [ { 'OPTIONS': { 'context_processors': [ 'django_settings_export.settings_export', ], }, }, ] MY_CHEESE = 'Camembert'; SETTINGS_EXPORT = [ 'MY_CHEESE', ]шаблон.HTML-код
<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" %}это защищает любые константы, которые вы не назвали от использования в шаблоне, и если вы хотите получить действительно причудливый, вы можете установить Кортеж в настройках и создать более одного тега шаблона для разных страниц, приложений или областей, а также просто объедините локальный кортеж с кортежем настроек по мере необходимости, а затем выполните понимание списка, чтобы увидеть, приемлемо ли значение.
Я согласен, на сложном сайте это немного упрощенно, но есть значения, которые было бы неплохо иметь универсально в шаблонах, и это, похоже, работает хорошо. Спасибо Бериславу за оригинальную идею!
я улучшил chrisdew это!--10--> (чтобы создать свой собственный тег) немного.
во-первых, создайте файл
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}}.
приведенный выше пример из 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', ... )
если используется представление на основе класса:
# # 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 }}
Если кто-то найдет этот вопрос, как я сделал, то я опубликую свое решение, которое работает на 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)шаблон:
{% 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/
добавление ответа с полными инструкциями по созданию пользовательского шаблона тега, который решает эту проблему, с 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" %}Это решение не будет работать с массивами, но если вам нужно, что вы могли бы положить много логики в шаблонах.
и 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")
Я нашел, что это самый простой подход для Django 1.3:
views.py
from local_settings import BASE_URL def root(request): return render_to_response('hero.html', {'BASE_URL': BASE_URL})герой.HTML-код
var BASE_URL = '{{ JS_BASE_URL }}';
если бы мы сравнивали контекст и теги шаблонов в одной переменной, то знание более эффективного варианта могло бы быть полезным. Однако вам может быть лучше окунуться в Настройки только из шаблонов, которым нужна эта переменная. В этом случае не имеет смысла передавать переменную во все шаблоны. Но если вы отправляете переменную в общий шаблон, такой как база.html шаблон, тогда это не имело бы значения в качестве базы.html шаблон отображается на каждый запрос, так что вы можно использовать любой из методов.
Если вы решили пойти с опцией template tags, то используйте следующий код, поскольку он позволяет вам передать по умолчанию значение in, на всякий случай переменная в вопросе была неопределенной.
пример: 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)

Comments