Puis - je accéder aux constantes settings.py des modèles de Django?

j'ai des trucs dans settings.py j'aimerais pouvoir y accéder à partir d'un modèle, mais je n'arrive pas à trouver comment le faire. J'ai déjà essayé

{{CONSTANT_NAME}}

mais ça ne semble pas marcher. Est-ce possible?

320
demandé sur Natiq Vahabov 2009-01-11 19:32:47

14 réponses

Django fournit l'accès à certaines constantes de paramètres fréquemment utilisés pour le modèle tel que settings.MEDIA_URL et certains paramètres de langue si vous utilisez django construit dans des vues génériques ou passer dans un argument de mot-clé d'instance de contexte dans la fonction de raccourci render_to_response . Voici un exemple de chaque cas:

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))

ces vues auront toutes les deux plusieurs paramètres fréquemment utilisés comme settings.MEDIA_URL disponibles pour le modèle comme {{ MEDIA_URL }} , etc.

si vous cherchez l'accès à d'autres constantes dans les paramètres, déballez simplement les constantes que vous voulez et ajoutez-les au dictionnaire de contexte que vous utilisez dans votre fonction de vue, comme ceci:

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)

Maintenant vous pouvez accéder à settings.FAVORITE_COLOR sur votre modèle comme {{ favorite_color }} .

157
répondu Prairiedogg 2009-06-01 01:29:27

si c'est une valeur que vous aimeriez avoir pour chaque requête et modèle, utiliser un context processor est plus approprié.

Voici comment:

  1. créez un fichier context_processors.py dans votre répertoire app. Disons que je veux avoir la valeur ADMIN_PREFIX_VALUE dans tous les contextes:

    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}
    
  2. ajoutez votre processeur de contexte à votre settings.py fichier:

    TEMPLATES = [{
        # whatever comes before
        'OPTIONS': {
            'context_processors': [
                # whatever comes before
                "your_app.context_processors.admin_media",
            ],
        }
    }]
    
  3. utilisez RequestContext dans votre vue pour ajouter vos processeurs de contexte dans votre modèle. Le render raccourci le fait automatiquement:

    from django.shortcuts import render
    
    def my_view(request):
        return render(request, "index.html")
    
  4. et enfin, dans votre modèle:

    ...
    <a href="{{ ADMIN_MEDIA_URL }}">path to admin media</a>
    ...
    
380
répondu bchhun 2016-06-17 16:25:26

je trouve l'approche la plus simple étant une étiquette de modèle unique:

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, "")

Utilisation:

{% settings_value "LANGUAGE_CODE" %}
227
répondu Berislav Lopac 2012-08-19 20:16:45

Check out django-settings-export (avertissement: je suis l'auteur de ce projet).

par exemple...

$ pip install django-settings-export

settings.py

TEMPLATES = [
    {
        'OPTIONS': {
            'context_processors': [
                'django_settings_export.settings_export',
            ],
        },
    },
]

MY_CHEESE = 'Camembert';

SETTINGS_EXPORT = [
    'MY_CHEESE',
]
Modèle

.html

<script>var MY_CHEESE = '{{ settings.MY_CHEESE }}';</script>
77
répondu Jakub 2015-12-28 20:46:10

une autre façon de faire ceci est de créer un tag template personnalisé qui peut vous permettre de pêcher des valeurs hors des paramètres.

@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))

vous pouvez alors utiliser:

{% value_from_settings "FQDN" %}

pour l'imprimer sur n'importe quelle page, sans sauter à travers les cerceaux contexte-processeur.

40
répondu fadedbee 2011-03-08 16:53:00

J'aime la solution de Berislav, parce que sur les sites simples, il est propre et efficace. Ce que je N'aime pas, c'est d'exposer toutes les constantes de réglages. Donc ce que j'ai fini par faire était ceci:

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 ''

Utilisation:

{% settings_value "CONSTANT_NAME_1" %}

cela protège toutes les constantes que vous n'avez pas nommées de l'utilisation dans le modèle, et si vous voulez obtenir vraiment de fantaisie, vous pouvez définir un tuple dans les paramètres, et créer plus d'une étiquette de modèle pour différentes pages, applications ou zones, et il suffit de combiner un tuple local avec les paramètres tuple si nécessaire, puis faire la compréhension de la liste pour voir si la valeur est acceptable.

Je suis d'accord, sur un site Complexe, c'est un peu simpliste, mais il y a des valeurs qui seraient bien d'avoir universellement dans les gabarits, et cela semble bien fonctionner. Merci à Berislav pour l'idée originale!

22
répondu MontyThreeCard 2016-11-14 16:40:04

j'ai amélioré chrisdew la réponse de (pour créer votre propre étiquette) un peu.

tout d'abord, créez le fichier yourapp/templatetags/value_from_settings.py dans lequel vous définissez votre propre nouvelle étiquette 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

vous pouvez utiliser cette balise dans votre modèle via:

{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" %}

ou via

{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" as my_fqdn %}

l'avantage de la notation as ... est que cela le rend facile à utiliser dans blocktrans bloque via un simple {{my_fqdn}} .

11
répondu pklaus 2017-05-23 12:18:30

l'exemple ci-dessus de bchhun est agréable sauf que vous devez explicitement construire votre dictionnaire de contexte à partir settings.py. Ci-dessous est un exemple non testé de la façon dont vous pourriez auto-construire le dictionnaire de contexte à partir de tous les attributs de cas supérieur de settings.py (re: "^[a-Z0-9_]+$").

à la fin 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',
...
)
7
répondu IanSR 2011-03-28 13:52:16

si vous utilisez une vue basée sur la classe:

#
# 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 }}
4
répondu Bill Paetzke 2013-04-28 22:43:18

si quelqu'un trouve cette question comme je l'ai fait, alors je posterai ma solution qui fonctionne sur Django 2.0:

cette balise assigne certains settings.py valeur de la variable à la variable du modèle:

Utilisation: {% 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)

votre modèle:

{% 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 %}

voir la documentation de Django: https://docs.djangoproject.com/en/2.0/howto/custom-template-tags /

3
répondu NullIsNot0 2018-01-17 13:56:51

ajouter une réponse avec des instructions complètes pour créer un tag template personnalisé qui résout ce problème, avec Django 2.0+

dans votre app-folder, créez un dossier appelé templatetags . Dans celui-ci, créer _ _ init__.py et custom_tags.py :

Custom tags folder structure

dans le custom_tags.py créer une fonction d'étiquette personnalisée qui fournit l'accès à une clé arbitraire dans le paramètres constante:

from django import template
from django.conf import settings

register = template.Library()

@register.simple_tag
def get_setting(name):
    return getattr(settings, name, "")

pour comprendre ce code je recommande la lecture de la section sur les étiquettes simples dans les docs Django.

ensuite, vous devez informer Django de cette (et de toute) étiquette personnalisée en chargeant ce fichier dans n'importe quel modèle où vous l'utiliserez. Tout comme vous avez besoin de charger la balise statique intégrée:

{% load custom_tags %}

avec il chargé, il peut être utilisé comme n'importe quelle autre étiquette, il suffit de fournir le réglage spécifique dont vous avez besoin retourné. Ainsi, si vous avez une variable BUILD_VERSION dans vos paramètres:

{% get_setting "BUILD_VERSION" %}

Cette solution ne fonctionnera pas avec les tableaux, mais si vous avez besoin que vous pourriez mettre à beaucoup de logique dans vos gabarits.

2
répondu Andreas Bergström 2018-09-26 20:02:53

Iansr et bchhun ont tous deux suggéré de remplacer TEMPLATE_CONTEXT_PROCESSEURS dans les paramètres. Soyez conscient que ce paramètre a une valeur par défaut qui peut causer des choses bizarres si vous l'annulez sans modifier les valeurs par défaut. Les valeurs par défaut ont également changé dans les versions récentes de Django.

https://docs.djangoproject.com/en/1.3/ref/settings/#template-context-processors

the default 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")
0
répondu MrOodles 2011-11-23 16:20:51

j'ai trouvé que C'était l'approche la plus simple pour Django 1.3:

  1. views.py

    from local_settings import BASE_URL
    
    def root(request):
        return render_to_response('hero.html', {'BASE_URL': BASE_URL})
    
  2. "151970920 héros".html

    var BASE_URL = '{{ JS_BASE_URL }}';
    
0
répondu Michael 2013-08-23 19:06:53

si nous devions comparer le contexte par rapport aux balises de modèle sur une seule variable, alors connaître l'option la plus efficace pourrait être benificial. Cependant, il est peut-être préférable de ne vous servir des paramètres que pour les modèles qui ont besoin de cette variable. Dans ce cas, il n'est pas logique de passer la variable dans tous les modèles. Mais si vous envoyez la variable dans un modèle commun tel que la base.modèle html, Alors il ne serait pas question que la base.modèle html est rendu sur chaque demande, afin de vous pouvez utiliser les deux méthodes.

si vous décidez d'utiliser l'option template tags, utilisez le code suivant car il vous permet de passer une valeur par défaut , juste au cas où la variable en question n'était pas définie.

exemple: get_from_settings my_variable as my_context_value

exemple: 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)
0
répondu un33k 2016-02-16 18:42:17