Posso acessar constantes em settings.py a partir de modelos no Django?

Eu tenho algumas coisas em settings.py que eu gostaria de poder acessar de um modelo, mas não consigo descobrir como fazê-lo. Eu já tentei

{{CONSTANT_NAME}} 

mas isso não parece funcionar. Isso é possível?

O Django fornece access a certas constantes de configurações freqüentemente usadas para o template, como settings.MEDIA_URL e algumas das configurações de idioma, se você usar views genéricas incorporadas do django ou passar um argumento de palavra-chave de instância de contexto na function de atalho render_to_response . Aqui está um exemplo 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)) 

Essas exibições terão várias configurações usadas com frequência, como settings.MEDIA_URL disponíveis para o modelo como {{ MEDIA_URL }} etc.

Se você está procurando access a outras constantes nas configurações, basta descompactar as constantes desejadas e adicioná-las ao dictionary de contexto que você está usando na function de visualização, assim:

 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) 

Agora você pode acessar settings.FAVORITE_COLOR no seu modelo como {{ favorite_color }} .

Se for um valor que você gostaria de ter para cada solicitação e modelo, usar um processador de contexto é mais apropriado.

Veja como:

  1. Crie um arquivo context_processors.py no diretório do seu aplicativo. Digamos que eu queira ter o valor ADMIN_PREFIX_VALUE em todos os contextos:

     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. adicione seu processador de contexto ao seu arquivo settings.py :

     TEMPLATES = [{ # whatever comes before 'OPTIONS': { 'context_processors': [ # whatever comes before "your_app.context_processors.admin_media", ], } }] 
  3. Use RequestContext na sua opinião para adicionar seus processadores de contexto ao seu modelo. O atalho de render faz isso automaticamente:

     from django.shortcuts import render def my_view(request): return render(request, "index.html") 
  4. e finalmente, no seu template:

     ... path to admin media ... 

Acho que a abordagem mais simples é uma tag de template única:

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

Confira django-settings-export (disclaimer: Eu sou o autor deste projeto).

Por exemplo…

 $ 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

  

Outra maneira de fazer isso é criar uma tag de modelo personalizada que permita que você pesquise valores fora das configurações.

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

Você pode então usar:

 {% value_from_settings "FQDN" %} 

para imprimi-lo em qualquer página, sem saltar através de aros de processador de contexto.

Eu gosto da solução da Berislav, porque em sites simples, é limpa e eficaz. O que eu não gosto é expor todas as constantes de configurações, quer queira quer não. Então o que acabei fazendo foi isso:

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

Isso protege quaisquer constantes que você não tenha chamado de uso no modelo e, se quiser ficar realmente chique, você pode definir uma tupla nas configurações e criar mais de uma tag de modelo para diferentes páginas, aplicativos ou áreas, e simplesmente combine uma tupla local com a tupla de configurações conforme necessário, em seguida, faça a compreensão da lista para ver se o valor é aceitável.
Eu concordo, em um site complexo, isso é um pouco simplista, mas existem valores que seria bom ter universalmente em modelos, e isso parece funcionar bem. Graças a Berislav pela ideia original!

Eu melhorei a resposta de chrisdew (para criar sua própria tag) um pouco.

Primeiro, crie o arquivo yourapp/templatetags/value_from_settings.py no qual você define sua própria nova 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 

Você pode usar essa tag no seu modelo por meio de:

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

ou via

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

A vantagem da notação as ... é que isso facilita o uso em blocos blocktrans através de um simples {{my_fqdn}} .

O exemplo acima do bchhun é legal, exceto que você precisa construir explicitamente seu dictionary de contexto a partir de settings.py. Abaixo está um exemplo UNTESTED de como você pode construir automaticamente o dictionary de contexto a partir de todos os atributos de maiúsculas de settings.py (re: “^ [A-Z0-9 _] + $”).

No final do 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', ... ) 

Se estiver usando uma visualização baseada em class:

 # # 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 }} 

Se alguém encontrar essa pergunta como eu fiz, postarei minha solução que funciona no Django 2.0:

Esta tag atribui algum valor de variável settings.py à variável do template:

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

Seu modelo:

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

Veja a documentação do Django sobre como criar tags de template customizadas aqui: https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/

Adicionando uma resposta com instruções completas para criar uma tag de template customizada que resolve isso, com Django 2.0

Na sua pasta de aplicativos, crie uma pasta chamada templatetags . Nele, crie __init__.py e custom_tags.py :

Estrutura de pastas de tags personalizadas

Em custom_tags.py, crie uma function de tag personalizada que fornece access a uma chave arbitrária na constante de configurações :

 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 esse código, eu recomendo ler a seção sobre tags simples nos documentos do Django.

Então, você precisa tornar o Django ciente desta (e de qualquer outra) tag customizada, carregando este arquivo em qualquer modelo onde você o usará. Assim como você precisa carregar a tag estática incorporada:

 {% load custom_tags %} 

Com ele carregado, ele pode ser usado como qualquer outra tag, basta fornecer a configuração específica que você precisa retornar. Então, se você tiver uma variável BUILD_VERSION nas suas configurações:

 {% get_setting "BUILD_VERSION" %} 

Esta solução não funcionará com arrays, mas se você precisar, pode estar colocando muita lógica em seus modelos.

IanSR e bchhun sugeriram replace TEMPLATE_CONTEXT_PROCESSORS nas configurações. Esteja ciente de que essa configuração tem um padrão que pode causar algumas falhas quando você a substitui sem redefinir os padrões. Os padrões também mudaram nas versões recentes do Django.

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

O padrão 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") 

Eu achei esta a abordagem mais simples para o 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 }}'; 

Se fôssemos comparar tags de contexto vs. template em uma única variável, então conhecer a opção mais eficiente poderia ser benéfico. No entanto, talvez seja melhor mergulhar nas configurações apenas de modelos que precisam dessa variável. Nesse caso, não faz sentido passar a variável para todos os modelos. Mas se você estiver enviando a variável para um modelo comum, como o template base.html, então não importa, pois o template base.html é renderizado em cada requisição, então você pode usar os methods.

Se você decidir usar a opção de tags de modelo, use o código a seguir, pois ele permite que você passe um valor padrão para o caso de a variável em questão não ser definida.

Exemplo: get_from_settings my_variable como my_context_value

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