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

J’ai quelques choses dans settings.py que je voudrais pouvoir accéder depuis un template, mais je ne peux pas comprendre comment le faire. J’ai déjà essayé

{{CONSTANT_NAME}} 

mais cela ne semble pas fonctionner. Est-ce possible?

Django permet d’accéder à certaines constantes de parameters fréquemment utilisées dans le modèle, telles que settings.MEDIA_URL et certains parameters de langue si vous utilisez les vues génériques intégrées de django ou si vous transmettez un argument de mot clé d’instance contextuelle 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 plusieurs parameters fréquemment utilisés tels que settings.MEDIA_URL disponible pour le modèle comme {{ MEDIA_URL }} , etc.

Si vous recherchez l’access à d’autres constantes dans les parameters, décompressez simplement les constantes souhaitées et ajoutez-les au dictionnaire de contexte que vous utilisez dans votre fonction d’affichage, 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) 

Vous pouvez maintenant accéder à settings.FAVORITE_COLOR sur votre modèle en tant que {{ favorite_color }} .

Si vous souhaitez avoir une valeur pour chaque requête et chaque modèle, l’utilisation d’un processeur de contexte est plus appropriée.

Voici comment:

  1. Créez un fichier context_processors.py dans votre répertoire d’application. Disons que je veux avoir la valeur ADMIN_PREFIX_VALUE dans chaque contexte:

     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 fichier settings.py :

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

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

     ... path to admin media ... 

Je trouve l’approche la plus simple étant une balise 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, "") 

Usage:

 {% settings_value "LANGUAGE_CODE" %} 

Découvrez 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', ] 

template.html

  

Une autre façon de faire est de créer une balise de modèle personnalisée qui peut vous permettre d’extraire des valeurs des parameters.

 @register.tag def value_from_settings(parser, token): try: # split_contents() knows not to split quoted ssortingngs. 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 du processeur de contexte.

J’aime la solution de Berislav, car sur des sites simples, elle est propre et efficace. Ce que je n’aime pas, c’est exposer toutes les constantes des réglages, bon gré mal gré. Donc, j’ai fini par faire 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 '' 

Usage:

 {% settings_value "CONSTANT_NAME_1" %} 

Cela protège toutes les constantes que vous n’avez pas nommées dans le modèle, et si vous voulez être vraiment sophistiqué, vous pouvez définir un tuple dans les parameters et créer plusieurs balises de modèle pour différentes pages, applications ou zones, et simplement Si nécessaire, combinez un tuple local avec les parameters tuple, puis faites 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 modèles, et cela semble fonctionner correctement. Merci à Berislav pour l’idée originale!

J’ai amélioré la réponse de chrisdew (pour créer votre propre tag).

Tout d’abord, créez le fichier yourapp/templatetags/value_from_settings.py dans lequel vous définissez votre propre tag value_from_settings :

 from django.template import TemplateSyntaxError, Variable, Node, Variable, Library from yourapp import settings register = Library() # I found some sortingcks 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 facilite son utilisation dans les blocs blocktrans via un simple {{my_fqdn}} .

L’exemple ci-dessus de bchhun est intéressant sauf que vous devez explicitement construire votre dictionnaire de contexte à partir de settings.py. Vous trouverez ci-dessous un exemple UNTESTED de la façon dont vous pouvez créer automatiquement le dictionnaire de contexte à partir de tous les atsortingbuts en majuscules de settings.py (re: “^ [A-Z0-9 _] + $”).

A 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', ... ) 

Si vous utilisez une vue basée sur une 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 }} 

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 une valeur de variable settings.py à la variable du template:

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.comstack_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 sur la façon de créer des balises de modèles personnalisées ici: https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/

Ajouter une réponse avec des instructions complètes pour créer une balise de modèle personnalisée qui résout ce problème, avec Django 2.0

Dans votre dossier app, créez un dossier appelé templatetags . Dans ce fichier , créez __init__.py et custom_tags.py :

Structure des dossiers de balises personnalisées

Dans le fichier custom_tags.py, créez une fonction de balise personnalisée qui donne access à une clé arbitraire dans les parameters constants:

 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 vous recommande de lire la section sur les balises simples dans les documents Django.

Ensuite, vous devez mettre Django au courant de cette balise personnalisée (et de toute autre balise supplémentaire) en chargeant ce fichier dans n’importe quel modèle où vous l’utiliserez. Tout comme vous avez besoin de charger le tag statique intégré:

 {% load custom_tags %} 

Une fois chargé, il peut être utilisé comme n’importe quelle autre balise, il suffit de fournir le paramètre spécifique dont vous avez besoin. Donc, si vous avez une variable BUILD_VERSION dans vos parameters:

 {% get_setting "BUILD_VERSION" %} 

Cette solution ne fonctionnera pas avec les baies, mais si vous en avez besoin, vous pouvez mettre beaucoup de logique dans vos modèles.

IanSR et bchhun ont tous deux suggéré de remplacer TEMPLATE_CONTEXT_PROCESSORS dans les parameters. Sachez que ce paramètre a une valeur par défaut qui peut causer des problèmes si vous le remplacez sans redéfinir les parameters 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

Le TEMPLATE_CONTEXT_PROCESSORS par défaut:

 TEMPLATE_CONTEXT_PROCESSORS = ("django.consortingb.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.consortingb.messages.context_processors.messages") 

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. hero.html

     var BASE_URL = '{{ JS_BASE_URL }}'; 

Si nous comparions les balises de contexte et les balises de modèle sur une seule variable, alors connaître l’option la plus efficace pourrait être bénéfique. Toutefois, il est préférable de ne consulter que les parameters provenant de modèles nécessitant cette variable. Dans ce cas, il est inutile de passer la variable dans tous les modèles. Mais si vous envoyez la variable dans un modèle commun tel que le template base.html, cela n’aura aucune importance car le template base.html est rendu à chaque requête, vous pouvez donc utiliser les deux méthodes.

Si vous décidez d’utiliser l’option tags de modèle, utilisez le code suivant, car il vous permet de transmettre une valeur par défaut , au cas où la variable en question ne serait pas définie.

Exemple: get_from_settings my_variable comme my_context_value

Exemple: get_from_settings my_variable my_default comme 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)