2010-10-28 22 views
14

Quiero tener algunas constantes en un proyecto de Django. Por ejemplo, digamos una constante llamada MIN_TIME_TEST.Definir constantes en Django

Me gustaría poder acceder a esta constante en dos lugares: desde mi código de Python, y desde dentro de cualquier plantilla.

¿Cuál es la mejor manera de hacerlo?

EDIT: Para aclarar, que sé de Procesadores contexto de la plantilla y alrededor de limitarse a poner las cosas en settings.py o algún otro archivo y simplemente importador.

Mi pregunta es, ¿cómo combino los dos enfoques sin violar la regla "No repetirme"? Basado en las respuestas hasta ahora, este es mi enfoque:

Me gustaría crear un archivo llamado global_constants.py, que tendrá una lista de constantes (cosas como MIN_TIME_TEST = 5). Puedo import este archivo en cualquier módulo para obtener las constantes.

Pero ahora, quiero crear el procesador de contexto que devuelve todas estas constantes. ¿Cómo puedo hacer esto automáticamente, sin tener que volver a enumerarlos en un diccionario, como en la respuesta de John Mee?

Respuesta

14

Tanto Luper como Vladimir están en lo cierto, pero necesitará ambos para completar sus requisitos.

  • Aunque, las constantes no necesitan estar en el settings.py, se puede poner en cualquier lugar e importarlos desde ese lugar en su código de la vista/modelo/módulo. A veces los pongo en el __init__.py si no me importa que se consideren relevantes a nivel mundial.

  • un procesador de contexto como este se asegurará de que las variables seleccionadas son a nivel mundial en el ámbito de plantilla

    def settings(request): 
        """ 
        Put selected settings variables into the default template context 
        """ 
        from django.conf import settings 
        return { 
         'DOMAIN':  settings.DOMAIN, 
         'GOOGLEMAPS_API_KEY': settings.GOOGLEMAPS_API_KEY, 
        } 
    

pero esto podría ser excesiva si eres nuevo en Django; tal vez solo está preguntando cómo poner variables en el alcance de la plantilla ...?

from django.conf import settings 

... 
# do stuff with settings.MIN_TIME_TEST as you wish 

render_to_response("the_template.html", { 
    "MIN_TIME_TEST": settings.MIN_TIME_TEST 
}, context_instance=RequestContext(request) 
+0

Gracias, de hecho es la dirección que quiero ir. Pero, por favor, consulte mi aclaración/otra pregunta, es decir, ¿cómo puedo hacer lo que dice sin tener que enumerar todas las constantes dos veces? –

+0

Envuélvalos todos en un diccionario y luego ponga ese diccionario en contexto. Accederá a ellos mediante notación de puntos. ej .: {{yourDict.yourConstant}} –

3

Considere ponerlo en settings.py de su aplicación. Por supuesto, para poder usarlo en la plantilla, deberá ponerlo a disposición de la plantilla como cualquier otra variable habitual.

2

Utilice context processors para tener sus constantes disponibles en todas las plantillas (settings.py es un buen lugar para definirlas como dijo Vladimir).

+0

¿Qué es una buena manera de sumarlos a los procesadores de contexto después de definir en settings.py? Prefiero no tener que repetir los nombres de todas las constantes más veces. –

+0

Toda la información está disponible en la página vinculada a Luper Rouch. Tendrá que crear una función de python que devolverá un diccionario de vars (que es donde devolverá sus constantes) y una lista de su función en la configuración de TEMPLATE_CONTEXT_PROCESSORS. –

0

En el procesador de contexto se puede usar algo como:

import settings 

context = {} 
for item in dir(settings): 
    #use some way to exclude __doc__, __name__, etc.. 
    if item[0:2] != '__': 
     context[item] = getattr(settings, item) 
4

Para construir sobre las respuestas de otras personas, he aquí una forma sencilla que le implementar esta forma:

En el archivo de configuración:

GLOBAL_SETTINGS = { 
    'MIN_TIME_TEST': 'blah', 
    'RANDOM_GLOBAL_VAR': 'blah', 
} 

Entonces, la construcción fuera de John Mee's context processor:

def settings(request): 
    """ 
    Put selected settings variables into the default template context 
    """ 
    from django.conf import settings 
    return settings.GLOBAL_SETTINGS 

Esto resolverá el problema DRY.

O, si usted sólo va a utilizar la configuración global de vez en cuando y que desee llamar desde dentro de la vista:

def view_func(request): 
    from django.conf import settings 
    # function code here 
    ctx = {} #context variables here 
    ctx.update(settings.GLOBAL_SETTINGS) 
    # whatever output you want here 
0

variante en la última parte de John Mee, con un poco de elaboración en la misma idea Jordan Reiter discute

Suponga que tiene algo en su configuración similar a lo que sugirió Jordan - en otras palabras, algo así como:

GLOBAL_SETTINGS = { 
    'SOME_CONST': 'thingy', 
    'SOME_OTHER_CONST': 'other_thingy', 
} 

Supongamos, además, que ya tiene un diccionario con algunas de las variables desea pasar su plantilla, tal vez pasado como argumentos a su vista. Llamémoslo my_dict. Supongamos que desea que los valores en my_dict anulen los del diccionario settings.GLOBAL_SETTINGS.

Es posible hacer algo en su opinión como:

def my_view(request, *args, **kwargs) 
    from django.conf import settings 
    my_dict = some_kind_of_arg_parsing(*args,**kwargs) 
    tmp = settings.GLOBAL_SETTINGS.copy() 
    tmp.update(my_dict) 
    my_dict = tmp 
    render_to_response('the_template.html', my_dict, context_instance=RequestContext(request)) 

Esto le permite tener los ajustes determinados a nivel mundial, a disposición de sus plantillas, y no requiere que escriba manualmente cada uno de ellos.

Si hacer no tiene ningún variables adicionales para aprobar la plantilla, ni ninguna necesidad de anular, sólo se puede hacer:

render_to_response('the_template.html', settings.GLOBAL_SETTINGS, context_instance=RequestContext(request)) 

La principal diferencia entre lo que estoy discutiendo aquí lo & Jordan tiene, es para él, settings.GLOBAL_SETTINGS anula todo lo que pueda tener en común con tu diccionario de contexto, y con el mío, mi diccionario de contexto anula settings.GLOBAL_SETTINGS. YMMV.

1

Los procesadores de contexto son más adecuados para manejar datos de objetos más dinámicos; se definen como un mapeo en el documentation y en muchos de los mensajes aquí se están modificando o transmitiendo a vistas: no lo hace tiene sentido que una plantilla pueda perder acceso a la información global porque, por ejemplo, olvidó usar un procesador de contexto especializado en la vista. Los datos son globales por definición & que une la vista a la plantilla.

Una mejor manera es definir una etiqueta de plantilla personalizada.De esta manera:

  • plantillas no están confiando en vistas a tener información mundial pasó a ellos
  • está seco-er: la aplicación que define la configuración global puede ser exportado a muchos proyectos, eliminando código común a través de proyectos
  • plantillas de decidir si tienen acceso a la información global, no las funciones de vista

en el ejemplo siguiente trato con su problema - la carga en este MIN_TIME_TEST variables - y un problema que comúnmente se enfrento, carga en URLs que cambian cuando mi entorno c ahorca

tengo 4 ambientes - 2 dev y 2 de producción:

  • Dev: django-servidor web, url: localhost: 8000
  • Dev: servidor web Apache: URL: sandbox.com -> resuelve a 127.0.0.1
  • servidor de caja de arena Prod, url: sandbox.domain.com
  • Prod servidor: URL: domain.com

lo hago en todos mis proyectos & mantener todas las direcciones URL en un archivo, global_settings.py por lo que es accesible desde el código. Defino una etiqueta de plantilla personalizada {% site_url%} que se puede (opcionalmente) cargar en cualquier plantilla

Creo una aplicación llamada global_settings, y me aseguro de que esté incluida en mi configuración.INSTALLED_APPS tuple.

Django recoge el texto de plantilla en los nodos con un método render() que indica cómo se deben mostrar los datos -. He creado un objeto que representa los datos por returnning valores en mi global_settings.py basado en el nombre pasado en

Parece que este:

from django import template 
import global_settings 

class GlobalSettingNode(template.Node): 
    def __init__(self, settingname): 
     self.settingname = settingname; 
    def render(self, context): 
     if hasattr(global_settings, self.settingname): 
      return getattr(global_settings, self.settingname) 
     else: 
      raise template.TemplateSyntaxError('%s tag does not exist' % self.settingname) 

Ahora, en global_settings.py Cómo registro un par de tags: site_url para mi ejemplo y min_test_time por su ejemplo. De esta forma, cuando se invoca {% min_time_test%} desde una plantilla, se llamará a get_min_time_test, que resuelve cargar en el valor = 5. En mi ejemplo, {% site_url%} hará una búsqueda basada en el nombre para que pueda mantener las 4 URL definidas a la vez y elegir qué entorno estoy usando. Esto es más flexible para mí que simplemente usar las configuraciones integradas de Django. Debug = indicador verdadero/falso.

from django import template 
from templatenodes import GlobalSettingNode 
register = template.Library() 


MIN_TIME_TEST = 5 

DEV_DJANGO_SITE_URL = 'http://localhost:8000/' 
DEV_APACHE_SITE_URL = 'http://sandbox.com/' 
PROD_SANDBOX_URL = 'http://sandbox.domain.com/' 
PROD_URL = 'http://domain.com/' 

CURRENT_ENVIRONMENT = 'DEV_DJANGO_SITE_URL' 



def get_site_url(parser, token): 
    return GlobalSettingNode(CURRENT_ENVIRONMENT) 

def get_min_time_test(parser, token): 
    return GlobalSettingNode('MIN_TIME_TEST') 

register.tag('site_url', get_site_url) 
register.tag('min_time_test', get_min_time_test) 

Tenga en cuenta que para que esto funcione, Django espera global_settings.py que se encuentra en una pitón empaquetado llamados templatetags debajo de la aplicación de Django. Mi aplicación Django que aquí se llama global_settings, por lo que mi estructura de directorios se parece a:

/project-name/global_settings/templatetags/global_settings.py etc.

Finalmente la plantilla elige si para cargar los valores globales o no , que es beneficioso para el rendimiento. Agregue esta línea a su plantilla para exponer todas las etiquetas registradas en global_settings.PY:

{% load global_settings %} 

Ahora, otros proyectos que necesitan MIN_TIME_TEST o estos ambientes expuestos simplemente puede instalar esta aplicación =)

Cuestiones relacionadas