2011-04-08 21 views
21

La documentación de Django mentions que se puede añadir sus propios ajustes a django.conf.settings. Así que si settings.py de mi proyecto define¿Cómo definir un valor predeterminado para establecer una costumbre Django

APPLES = 1 

puedo acceder con settings.APPLES que en mis aplicaciones en ese proyecto.

Pero si mi settings.py no define ese valor, acceder a settings.APPLES obviamente no funcionará. ¿Hay alguna manera de definir un valor predeterminado para APPLES que se utiliza si no existe un ajuste explícito en settings.py?

me gustaría mejor para definir el valor por defecto en el módulo/paquete que requiere el ajuste.

Respuesta

24

En mis aplicaciones, que tienen un archivo settings.py separado. En ese archivo tengo una función get() que busca en el archivo de settings.py de proyectos y si no se encuentra, devuelve el valor predeterminado.

from django.conf import settings 

def get(key, default): 
    return getattr(settings, key, default) 


APPLES = get('APPLES', 1) 

Entonces donde necesito acceder MANZANAS que tengo:

from myapp import settings as myapp_settings 

myapp_settings.APPLES 

Esto permite una anulación en los proyectos settings.py, getattr comprobará primero y devolver el valor si el atributo se encuentra o usa el predeterminado definido en el archivo de configuración de tus aplicaciones.

+0

¿No es esto frágil? ¿No depende de que el proyecto 'settings.py' se importe antes de' app_settings.py'? – Flimm

1

A partir de la respuesta de Mike, ahora envuelto el ajuste por defecto de manipulación en una clase con interfaz fácil de usar.

módulo de Ayudante:

from django.conf import settings 

class SettingsView(object): 
    class Defaults(object): 
     pass 

    def __init__(self): 
     self.defaults = SettingsView.Defaults() 

    def __getattr__(self, name): 
     return getattr(settings, name, getattr(self.defaults, name)) 

Uso:

from localconf import SettingsView 

settings = SettingsView() 
settings.defaults.APPLES = 1 

print settings.APPLES 

Esto imprime el valor de django.conf.settings, o el valor por defecto si no se establece allí. Este objeto settings también se puede usar para acceder a todos los valores de configuración estándar.

+0

Creo que la configuración específica de la aplicación debe nombrarse explícitamente y ser diferente de la configuración principal, solo para facilitar la lectura. –

1

Usted puede comprobar para ver si se define la configuración, y si no, le dan el valor por defecto. Por ejemplo, puede definir una función auxiliar setting_default así:

from django.conf import settings 

def setting_default(name, default_value): 
    value = getattr(settings, name, default_value) 
    setattr(settings, name, value) 

y luego usarlo en la aplicación que requiere el ajuste (tal vez en models.py) así:

setting_default('APPLES', 1) 

De esta manera quien sea que esté utilizando su la aplicación no tiene que hacer nada especial.

10

¿Qué tal:

getattr(app_settings, 'SOME_SETTING', 'default value') 
+0

Esto es mucho más simple que algunas de las otras sugerencias aquí, pero si tiene la intención de usar una configuración/variable más de una vez, está rompiendo el concepto DRY, en cuyo caso las otras soluciones podrían funcionar. Pienso :) – daniel

+0

¿Cómo se rompe DRY? – Charlie

+0

Si tiene la intención de usar SOME_SETTING más de una vez en su aplicación, tendrá que colocar este 'getattr (app_settings, 'SOME_SETTING', default_value)' en cualquier lugar que lo use – daniel

5

Aquí hay dos soluciones. Para ambos puede establecer archivos settings.py en sus aplicaciones y llenarlos con valores predeterminados.

valor predeterminado Configurar para una sola aplicación

Uso from MYAPP import settings en lugar de from django.conf import settings en el código.

Editar YOURAPP/__init__.py:

from django.conf import settings as user_settings 
from . import settings as default_settings 

class AppSettings: 
    def __getattr__(self, name): 
     # If the setting you want is filled by the user, let's use it. 
     if hasattr(user_settings, name): 
      return getattr(user_settings, name) 

     # If the setting you want has a default value, let's use it. 
     if hasattr(default_settings, name): 
      return getattr(default_settings, name) 

     raise AttributeError("'Settings' object has no attribute '%s'" % name) 

settings = AppSettings() 

Configurar valores por defecto para un proyecto entero

Uso from MYPROJECT import settings en lugar de from django.conf import settings en el código.

Editar MYPROJECT/MYPROJECT/__init__.py

import os, sys, importlib 
from . import settings as user_settings 

def get_local_apps(): 
    """Returns the locally installed apps names""" 
    apps = [] 
    for app in user_settings.INSTALLED_APPS: 
     path = os.path.join(user_settings.BASE_DIR, app) 
     if os.path.exists(path) and app != __name__: 
      apps.append(sys.modules[app]) 
    return apps 

class AppSettings: 
    SETTINGS_MODULE = 'settings' 

    def __getattr__(self, setting_name): 

     # If the setting you want is filled by the user, let's use it. 
     if hasattr(user_settings, setting_name): 
      return getattr(user_settings, setting_name) 

     # Let's check every local app loaded by django. 
     for app in get_local_apps(): 
      module_source = os.path.join(app.__path__[0], "%s.py" % self.SETTINGS_MODULE) 
      module_binary = os.path.join(app.__path__[0], "%s.pyc" % self.SETTINGS_MODULE) 
      if os.path.exists(module_source) or os.path.exists(module_binary): 
       module = importlib.import_module("%s.%s" % (app.__name__, self.SETTINGS_MODULE)) 

       # Let's take the first default value for this setting we can find in any app 
       if hasattr(module, setting_name): 
        return getattr(module, setting_name) 

     raise AttributeError("'Settings' object has no attribute '%s'" % setting_name) 

settings = AppSettings() 

Esta solución puede parecer más fácil de instalar, pero no garantiza que se devolverá el valor por defecto. Si varias aplicaciones declaran la misma variable en su settings.py, no puede estar seguro de cuál devolverá el valor predeterminado que solicitó.

0

Recientemente tuve el mismo problema y creé una aplicación Django que está diseñada para ser utilizada exactamente en tal caso. Le permite definir valores predeterminados para ciertas configuraciones. Luego, primero verifica si la configuración se establece en el archivo de configuración global. Si no, devolverá el valor predeterminado.

He extendido a permitir también por alguna comprobación de tipos o manipulación previa del valor predeterminado (por ejemplo, una ruta de clase de puntos se puede convertir a la clase en sí de la carga)

La aplicación se puede encontrar en: https://pypi.python.org/pypi?name=django-pluggableappsettings&version=0.2.0&:action=display

Cuestiones relacionadas