Tengo algunas cosas en settings.py a las que me gustaría poder acceder desde una plantilla, pero no puedo entender cómo hacerlo. Ya lo intenté
{{CONSTANT_NAME}}
Pero eso no parece funcionar. es posible?
Tengo algunas cosas en settings.py a las que me gustaría poder acceder desde una plantilla, pero no puedo entender cómo hacerlo. Ya lo intenté
{{CONSTANT_NAME}}
Pero eso no parece funcionar. es posible?
Respuestas:
Django proporciona acceso a ciertas constantes de configuración de uso frecuente de la plantilla, como settings.MEDIA_URL
algunas de las configuraciones de idioma, si utiliza las vistas genéricas integradas de django o pasa un argumento de palabra clave de instancia de contexto en la render_to_response
función de acceso directo. Aquí hay un ejemplo de cada caso:
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))
Estas vistas tendrán varias configuraciones de uso frecuente como settings.MEDIA_URL
disponibles para la plantilla como{{ MEDIA_URL }}
, etc.
Si está buscando acceso a otras constantes en la configuración, simplemente desempaquete las constantes que desee y agréguelas al diccionario de contexto que está utilizando en su función de visualización, de esta manera:
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)
Ahora puede acceder settings.FAVORITE_COLOR
a su plantilla como {{ favorite_color }}
.
django-settings-export
para evitar la necesidad de escribir este código en cada vista.
Si es un valor que le gustaría tener para cada solicitud y plantilla, es más apropiado usar un procesador de contexto .
Así es cómo:
Crea un context_processors.py
archivo en el directorio de tu aplicación. Digamos que quiero tener el ADMIN_PREFIX_VALUE
valor en cada contexto:
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}
agregue su procesador de contexto a su archivo settings.py :
TEMPLATES = [{
# whatever comes before
'OPTIONS': {
'context_processors': [
# whatever comes before
"your_app.context_processors.admin_media",
],
}
}]
Use RequestContext
en su vista para agregar sus procesadores de contexto en su plantilla. El render
atajo hace esto automáticamente:
from django.shortcuts import render
def my_view(request):
return render(request, "index.html")
y finalmente, en tu plantilla:
...
<a href="{{ ADMIN_MEDIA_URL }}">path to admin media</a>
...
context_process.py
justo al lado de mi settings.py
archivo y agregué "context_processors.admin_media"
a mi TEMPLATE_CONTEXT_PROCESSORS
lista. Además, es posible que desee agregar una nota en su respuesta sobre el hecho de que el valor predeterminado de TEMPLATE_CONTEXT_PROCESSORS no está vacío, por lo que si algún código existente usa alguno de los valores establecidos por esos procesadores de contexto predeterminados, no funcionarán a menos que los vuelva a agregar a la lista explícitamente.
render
acceso directo para evitar tener que incluir explícitamente RequestContext: docs.djangoproject.com/en/1.6/topics/http/shortcuts/#render
Encuentro que el enfoque más simple es una sola etiqueta de plantilla personalizada :
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, "")
Uso:
{% settings_value "LANGUAGE_CODE" %}
{% settings_value "DATABASES" %}
:? Este caso de uso debería hacer obvio por qué la configuración no está disponible en las plantillas para empezar.
templatetags
carpeta dentro de su aplicación con un __init__.py
archivo vacío y este código como settings.py
dentro de esa carpeta. 2) en su plantilla agrega {% load settings %}
y luego usa su nueva etiqueta.
Echa un vistazo django-settings-export
(descargo de responsabilidad: soy el autor de este proyecto).
Por ejemplo...
$ 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
y norender_to_response
Otra forma de hacerlo es crear una etiqueta de plantilla personalizada que le permita extraer valores de la configuración.
@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))
Entonces puedes usar:
{% value_from_settings "FQDN" %}
para imprimirlo en cualquier página, sin saltar por los aros del procesador de contexto.
Me gusta la solución de Berislav, porque en sitios simples, es limpia y efectiva. Lo que NO me gusta es exponer todas las constantes de configuración willy-nilly. Entonces, lo que terminé haciendo fue esto:
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 ''
Uso:
{% settings_value "CONSTANT_NAME_1" %}
Esto protege las constantes que no ha nombrado del uso en la plantilla, y si desea ser realmente elegante, puede establecer una tupla en la configuración y crear más de una etiqueta de plantilla para diferentes páginas, aplicaciones o áreas, y simplemente combine una tupla local con la tupla de configuración según sea necesario, luego comprenda la lista para ver si el valor es aceptable.
Estoy de acuerdo, en un sitio complejo, esto es un poco simplista, pero hay valores que sería bueno tener universalmente en las plantillas, y esto parece funcionar bien. ¡Gracias a Berislav por la idea original!
if name in ALLOWABLE_VALUES: ...
'val' in ('val_first', 'second_val',)
es False
, no hay problema de subcadena aquí.
if
declaración? quiero verificar el DEBUG
valor
Mejoré un poco la respuesta de chrisdew (para crear tu propia etiqueta).
Primero, cree el archivo yourapp/templatetags/value_from_settings.py
en el que define su propia etiqueta nueva 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
Puede usar esta etiqueta en su plantilla a través de:
{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" %}
o vía
{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" as my_fqdn %}
La ventaja de la as ...
notación es que esto hace que sea fácil de usar en blocktrans
bloques a través de un simple {{my_fqdn}}
.
Agregar una respuesta con instrucciones completas para crear una etiqueta de plantilla personalizada que resuelva esto, con Django 2.0+
En su carpeta de aplicaciones, cree una carpeta llamada templatetags . En él, cree __init__.py y custom_tags.py :
En custom_tags.py, cree una función de etiqueta personalizada que proporcione acceso a una clave arbitraria en la configuración constante:
from django import template
from django.conf import settings
register = template.Library()
@register.simple_tag
def get_setting(name):
return getattr(settings, name, "")
Para entender este código, recomiendo leer la sección sobre etiquetas simples en los documentos de Django.
Luego, debe informar a Django sobre esta etiqueta personalizada (y cualquier otra adicional) cargando este archivo en cualquier plantilla donde la vaya a usar. Al igual que necesita cargar la etiqueta estática integrada:
{% load custom_tags %}
Una vez cargado, puede usarse como cualquier otra etiqueta, solo proporcione la configuración específica que necesita devolver. Entonces, si tiene una variable BUILD_VERSION en su configuración:
{% get_setting "BUILD_VERSION" %}
Esta solución no funcionará con matrices, pero si lo necesita, podría estar poniendo mucha lógica en sus plantillas.
Nota: Una solución más limpia y segura probablemente sería crear un procesador de contexto personalizado donde agregue la configuración que necesita a un contexto disponible para todas las plantillas. De esta forma, reduce el riesgo de generar configuraciones confidenciales en sus plantillas por error.
Agregue este código a un archivo llamado context_processors.py
:
from django.conf import settings as django_settings
def settings(request):
return {
'settings': django_settings,
}
Y luego, en su archivo de configuración, incluya una ruta como 'speedy.core.base.context_processors.settings'
(con el nombre y la ruta de su aplicación) en la 'context_processors'
configuración de TEMPLATES
.
(Puede ver, por ejemplo, settings / base.py y context_processors.py ).
Luego puede usar la configuración específica en cualquier código de plantilla. Por ejemplo:
{% if settings.SITE_ID == settings.SPEEDY_MATCH_SITE_ID %}
Actualización: el código anterior expone toda la configuración a plantillas, incluida información confidencial como la suya SECRET_KEY
. Un hacker podría abusar de esta función para mostrar dicha información en las plantillas. Si desea exponer solo configuraciones específicas a las plantillas, use este código en su lugar:
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
. Un pirata informático puede abusar de esta función para mostrar dicha información en las plantillas.
El ejemplo anterior de bchhun es bueno, excepto que necesita construir explícitamente su diccionario de contexto desde settings.py. A continuación se muestra un ejemplo NO PROBADO de cómo podría crear automáticamente el diccionario de contexto a partir de todos los atributos en mayúsculas de settings.py (re: "^ [A-Z0-9 _] + $").
Al final de 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',
...
)
Si alguien encuentra esta pregunta como yo, entonces publicaré mi solución que funciona en Django 2.0:
Esta etiqueta asigna algunos valores de variable settings.py a la variable de la plantilla:
Uso: {% 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 %}
Consulte la documentación de Django sobre cómo crear etiquetas de plantilla personalizadas aquí: https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/
{% if settings_debug %}
{% if settings_debug == True %}
a su sugerencia{% if settings_debug %}
Si usa una vista basada en clases:
#
# 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 }}
Tanto IanSR como bchhun sugirieron anular TEMPLATE_CONTEXT_PROCESSORS en la configuración. Tenga en cuenta que esta configuración tiene un valor predeterminado que puede causar algunos problemas si lo anula sin restablecer los valores predeterminados. Los valores predeterminados también han cambiado en versiones recientes de Django.
https://docs.djangoproject.com/en/1.3/ref/settings/#template-context-processors
El TEMPLATE_CONTEXT_PROCESSORS predeterminado:
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")
Si tuviéramos que comparar etiquetas de contexto frente a plantillas en una sola variable, entonces conocer la opción más eficiente podría ser beneficioso. Sin embargo, es mejor que se sumerja en la configuración solo de las plantillas que necesitan esa variable. En ese caso, no tiene sentido pasar la variable a todas las plantillas. Pero si está enviando la variable a una plantilla común como la plantilla base.html, entonces no importaría ya que la plantilla base.html se representa en cada solicitud, por lo que puede usar cualquiera de los métodos.
Si decide utilizar la opción de etiquetas de plantilla, utilice el siguiente código, ya que le permite pasar un valor predeterminado valor , en caso de que la variable en cuestión no definida.
Ejemplo: get_from_settings my_variable como my_context_value
Ejemplo: get_from_settings my_variable my_default como 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)