Mam pewne ustawienia w pliku settings.py, do których chciałbym uzyskać dostęp z szablonu, ale nie wiem, jak to zrobić. Już próbowałem
{{CONSTANT_NAME}}
ale to nie działa. czy to możliwe?
Mam pewne ustawienia w pliku settings.py, do których chciałbym uzyskać dostęp z szablonu, ale nie wiem, jak to zrobić. Już próbowałem
{{CONSTANT_NAME}}
ale to nie działa. czy to możliwe?
Odpowiedzi:
Django zapewnia dostęp do pewnych, często używanych stałych ustawień szablonu, takich jak settings.MEDIA_URL
niektóre ustawienia języka, jeśli używasz wbudowanych widoków ogólnych django lub przekazujesz argument render_to_response
funkcji kontekstowej słowa kluczowego w funkcji skrótu. Oto przykład każdego przypadku:
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))
Te widoki będą miały kilka często używanych ustawień, takich jak settings.MEDIA_URL
dostępne dla szablonu jako {{ MEDIA_URL }}
itp.
Jeśli szukasz dostępu do innych stałych w ustawieniach, po prostu rozpakuj wybrane stałe i dodaj je do słownika kontekstowego, którego używasz w funkcji widoku, w następujący sposób:
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)
Teraz możesz uzyskać dostęp settings.FAVORITE_COLOR
do swojego szablonu jako {{ favorite_color }}
.
django-settings-export
się unikać konieczności pisania tego kodu w każdym widoku.
Jeśli chcesz mieć wartość dla każdego żądania i szablonu, bardziej odpowiednie jest użycie procesora kontekstu .
Oto jak:
Utwórz context_processors.py
plik w katalogu aplikacji. Powiedzmy, że chcę mieć ADMIN_PREFIX_VALUE
wartość w każdym kontekście:
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}
dodaj procesor kontekstowy do pliku settings.py :
TEMPLATES = [{
# whatever comes before
'OPTIONS': {
'context_processors': [
# whatever comes before
"your_app.context_processors.admin_media",
],
}
}]
Użyj RequestContext
w widoku, aby dodać procesory kontekstowe do szablonu. render
Skrót robi to automatycznie:
from django.shortcuts import render
def my_view(request):
return render(request, "index.html")
i wreszcie w szablonie:
...
<a href="{{ ADMIN_MEDIA_URL }}">path to admin media</a>
...
context_process.py
tuż obok mojego settings.py
pliku i dodałem "context_processors.admin_media"
do mojej TEMPLATE_CONTEXT_PROCESSORS
listy. Ponadto możesz dodać notatkę w odpowiedzi na temat faktu, że domyślna wartość TEMPLATE_CONTEXT_PROCESSORS nie jest pusta, więc jeśli jakikolwiek istniejący kod używa dowolnej wartości ustawionej przez te domyślne procesory kontekstowe, nie będą działać, chyba że dodasz je z powrotem do listy jawnie.
render
skrótu, aby uniknąć konieczności jawnego dołączania
Uważam, że najprostszym podejściem jest pojedynczy niestandardowy tag szablonu :
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, "")
Stosowanie:
{% settings_value "LANGUAGE_CODE" %}
{% settings_value "DATABASES" %}
:? Ten przypadek użycia powinien wyjaśnić, dlaczego ustawienia nie są dostępne w szablonach na początek.
templatetags
folder w aplikacji z pustym __init__.py
plikiem i tym kodem jak settings.py
w tym folderze. 2) w szablonie dodajesz, {% load settings %}
a następnie używasz nowego tagu!
Sprawdź django-settings-export
(zastrzeżenie: jestem autorem tego projektu).
Na przykład...
$ 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
a nierender_to_response
Innym sposobem na to jest utworzenie niestandardowego znacznika szablonu, który pozwala wyłowić wartości z ustawień.
@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))
Następnie możesz użyć:
{% value_from_settings "FQDN" %}
aby wydrukować go na dowolnej stronie, bez przeskakiwania przez pętle procesora kontekstowego.
Podoba mi się rozwiązanie Berislava, ponieważ na prostych stronach jest czyste i skuteczne. NIE podoba mi się ujawnianie wszystkich stałych ustawień willy-nilly. Skończyło się na tym, że:
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 ''
Stosowanie:
{% settings_value "CONSTANT_NAME_1" %}
Chroni to wszelkie stałe, które nie zostały nazwane przed użyciem w szablonie, a jeśli chcesz być naprawdę fantazyjny, możesz ustawić krotkę w ustawieniach i utworzyć więcej niż jeden znacznik szablonu dla różnych stron, aplikacji lub obszarów i po prostu w razie potrzeby połącz lokalną krotkę z krotką ustawień, a następnie przejrzyj listę, aby sprawdzić, czy wartość jest akceptowalna.
Zgadzam się, na złożonej stronie jest to nieco uproszczone, ale istnieją wartości, które dobrze byłoby mieć uniwersalnie w szablonach, i wydaje się, że działa to dobrze. Dzięki Berislav za oryginalny pomysł!
if name in ALLOWABLE_VALUES: ...
'val' in ('val_first', 'second_val',)
jest False
, nie ma podciąg problem tutaj.
if
zestawieniu? Chcę sprawdzić DEBUG
wartość
Poprawiłem trochę odpowiedź chrisdew (aby utworzyć własny tag).
Najpierw utwórz plik, yourapp/templatetags/value_from_settings.py
w którym zdefiniujesz swój własny tag 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
Możesz użyć tego tagu w swoim szablonie poprzez:
{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" %}
lub przez
{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" as my_fqdn %}
Zaletą tego as ...
zapisu jest to, że dzięki temu można go łatwo używać w blocktrans
blokach {{my_fqdn}}
.
Dodanie odpowiedzi z kompletnymi instrukcjami tworzenia niestandardowego znacznika szablonu, który rozwiązuje ten problem za pomocą Django 2.0+
W folderze aplikacji utwórz folder o nazwie szablony . W nim utwórz __init__.py i custom_tags.py :
W custom_tags.py utwórz niestandardową funkcję znacznika, która zapewnia dostęp do dowolnego klucza w stałej ustawień :
from django import template
from django.conf import settings
register = template.Library()
@register.simple_tag
def get_setting(name):
return getattr(settings, name, "")
Aby zrozumieć ten kod, polecam przeczytanie sekcji o prostych tagach w dokumentach Django.
Następnie musisz poinformować Django o tym (i dowolnym dodatkowym) niestandardowym tagu, ładując ten plik do dowolnego szablonu, w którym go użyjesz. Tak jak musisz załadować wbudowany tag statyczny:
{% load custom_tags %}
Po załadowaniu może być używany tak jak każdy inny tag, wystarczy podać określone ustawienie, które chcesz zwrócić. Więc jeśli masz zmienną BUILD_VERSION w swoich ustawieniach:
{% get_setting "BUILD_VERSION" %}
To rozwiązanie nie będzie działać z tablicami, ale jeśli jest to potrzebne, być może logujesz się w szablonach.
Uwaga: Bardziej czystym i bezpiecznym rozwiązaniem byłoby prawdopodobnie utworzenie niestandardowego procesora kontekstowego, w którym dodasz potrzebne ustawienia do kontekstu dostępne dla wszystkich szablonów. W ten sposób zmniejszasz ryzyko przypadkowego wprowadzenia wrażliwych ustawień w szablonach.
Dodaj ten kod do pliku o nazwie context_processors.py
:
from django.conf import settings as django_settings
def settings(request):
return {
'settings': django_settings,
}
A następnie w pliku ustawień dołącz ścieżkę, taką jak 'speedy.core.base.context_processors.settings'
(z nazwą i ścieżką aplikacji) w 'context_processors'
ustawieniach w TEMPLATES
.
(Możesz zobaczyć na przykład ustawienia / base.py i context_processors.py ).
Następnie możesz użyć określonego ustawienia w dowolnym kodzie szablonu. Na przykład:
{% if settings.SITE_ID == settings.SPEEDY_MATCH_SITE_ID %}
Aktualizacja: powyższy kod udostępnia wszystkie ustawienia szablonów, w tym poufne informacje, takie jak Twoje SECRET_KEY
. Haker może wykorzystać tę funkcję do wyświetlania takich informacji w szablonach. Jeśli chcesz udostępnić szablony tylko określone ustawienia, użyj tego kodu:
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
. Haker może wykorzystać tę funkcję do wyświetlenia takich informacji w szablonach.
Powyższy przykład z bchhun jest ładny, z wyjątkiem tego, że musisz jawnie zbudować słownik kontekstowy z settings.py. Poniżej znajduje się NIETESTOWANY przykład, w jaki sposób można automatycznie zbudować słownik kontekstowy ze wszystkich dużych atrybutów settings.py (re: "^ [A-Z0-9 _] + $").
Na końcu 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',
...
)
Jeśli ktoś znajdzie to pytanie tak jak ja, opublikuję moje rozwiązanie, które działa na Django 2.0:
Ten znacznik przypisuje niektóre wartości zmiennej settings.py do zmiennej szablonu:
Stosowanie: {% 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 %}
Zobacz dokumentację Django, jak tworzyć niestandardowe tagi szablonów tutaj: https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/
{% if settings_debug %}
{% if settings_debug == True %}
na sugerowany{% if settings_debug %}
Jeśli używasz widoku klasowego:
#
# 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 }}
Zarówno IanSR, jak i bchhun zasugerowały zastąpienie TEMPLATE_CONTEXT_PROCESSORS w ustawieniach. Pamiętaj, że to ustawienie ma wartość domyślną, która może powodować pewne nieprzyjemne rzeczy, jeśli zastąpisz ją bez ponownego ustawienia wartości domyślnych. Domyślne ustawienia również uległy zmianie w ostatnich wersjach Django.
https://docs.djangoproject.com/en/1.3/ref/settings/#template-context-processors
Domyślne 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")
Gdybyśmy porównali znaczniki kontekstu z szablonem na jednej zmiennej, znajomość bardziej wydajnej opcji może być korzystna. Lepiej jednak zanurzyć się w ustawieniach tylko z szablonów, które potrzebują tej zmiennej. W takim przypadku przekazanie zmiennej do wszystkich szablonów nie ma sensu. Ale jeśli wysyłasz zmienną do wspólnego szablonu, takiego jak szablon base.html, nie miałoby to znaczenia, ponieważ szablon base.html jest renderowany przy każdym żądaniu, więc możesz użyć dowolnej z metod.
Jeśli zdecydujesz się skorzystać z opcji tagów szablonów, użyj następującego kodu, ponieważ pozwala on przekazać wartość domyślną wartość , na wypadek, gdyby zmienna, o której mowa, była niezdefiniowana.
Przykład: get_from_settings moja_zmienna jako moja_kontekstowa wartość
Przykład: 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
w oprogramowaniu końcowym, aby zrobić to za Ciebie.