Fixed #1321 -- Made DJANGO_SETTINGS_MODULE optional. You can now call django.conf.settings.configure() to set settings manually if you don't have a settings module. Thanks, Malcolm Tredinnick, Luke Plant, Fredrik Lundh
git-svn-id: http://code.djangoproject.com/svn/django/trunk@2927 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
27612d8b7d
commit
c643e12faf
|
@ -12,10 +12,61 @@ from django.conf import global_settings
|
|||
|
||||
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
|
||||
|
||||
class LazySettings:
|
||||
"""
|
||||
A lazy proxy for either global Django settings or a custom settings object.
|
||||
The user can manually configure settings prior to using them. Otherwise,
|
||||
Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
|
||||
"""
|
||||
def __init__(self):
|
||||
# _target must be either None or something that supports attribute
|
||||
# access (getattr, hasattr, etc).
|
||||
self._target = None
|
||||
|
||||
def __getattr__(self, name):
|
||||
if self._target is None:
|
||||
self._import_settings()
|
||||
if name == '__members__':
|
||||
# Used to implement dir(obj), for example.
|
||||
return self._target.get_all_members()
|
||||
return getattr(self._target, name)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name == '_target':
|
||||
self.__dict__['_target'] = value
|
||||
else:
|
||||
setattr(self._target, name, value)
|
||||
|
||||
def _import_settings(self):
|
||||
"""
|
||||
Load the settings module pointed to by the environment variable. This
|
||||
is used the first time we need any settings at all, if the user has not
|
||||
previously configured the settings manually.
|
||||
"""
|
||||
try:
|
||||
settings_module = os.environ[ENVIRONMENT_VARIABLE]
|
||||
if not settings_module: # If it's set but is an empty string.
|
||||
raise KeyError
|
||||
except KeyError:
|
||||
raise EnvironmentError, "Environment variable %s is undefined." % ENVIRONMENT_VARIABLE
|
||||
|
||||
self._target = Settings(settings_module)
|
||||
|
||||
def configure(self, default_settings=global_settings, **options):
|
||||
"""
|
||||
Called to manually configure the settings. The 'default_settings'
|
||||
parameter sets where to retrieve any unspecified values from (its
|
||||
argument must support attribute access (__getattr__)).
|
||||
"""
|
||||
if self._target != None:
|
||||
raise EnvironmentError, 'Settings already configured.'
|
||||
holder = UserSettingsHolder(default_settings)
|
||||
for name, value in options.items():
|
||||
setattr(holder, name, value)
|
||||
self._target = holder
|
||||
|
||||
class Settings:
|
||||
|
||||
def __init__(self, settings_module):
|
||||
|
||||
# update this dict from global settings (but only for ALL_CAPS settings)
|
||||
for setting in dir(global_settings):
|
||||
if setting == setting.upper():
|
||||
|
@ -27,7 +78,7 @@ class Settings:
|
|||
try:
|
||||
mod = __import__(self.SETTINGS_MODULE, '', '', [''])
|
||||
except ImportError, e:
|
||||
raise EnvironmentError, "Could not import settings '%s' (is it on sys.path?): %s" % (self.SETTINGS_MODULE, e)
|
||||
raise EnvironmentError, "Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (self.SETTINGS_MODULE, e)
|
||||
|
||||
# Settings that should be converted into tuples if they're mistakenly entered
|
||||
# as strings.
|
||||
|
@ -56,18 +107,32 @@ class Settings:
|
|||
# move the time zone info into os.environ
|
||||
os.environ['TZ'] = self.TIME_ZONE
|
||||
|
||||
# try to load DJANGO_SETTINGS_MODULE
|
||||
try:
|
||||
settings_module = os.environ[ENVIRONMENT_VARIABLE]
|
||||
if not settings_module: # If it's set but is an empty string.
|
||||
raise KeyError
|
||||
except KeyError:
|
||||
raise EnvironmentError, "Environment variable %s is undefined." % ENVIRONMENT_VARIABLE
|
||||
def get_all_members(self):
|
||||
return dir(self)
|
||||
|
||||
# instantiate the configuration object
|
||||
settings = Settings(settings_module)
|
||||
class UserSettingsHolder:
|
||||
"""
|
||||
Holder for user configured settings.
|
||||
"""
|
||||
# SETTINGS_MODULE does not really make sense in the manually configured
|
||||
# (standalone) case.
|
||||
SETTINGS_MODULE = None
|
||||
|
||||
def __init__(self, default_settings):
|
||||
"""
|
||||
Requests for configuration variables not in this class are satisfied
|
||||
from the module specified in default_settings (if possible).
|
||||
"""
|
||||
self.default_settings = default_settings
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.default_settings, name)
|
||||
|
||||
def get_all_members(self):
|
||||
return dir(self) + dir(self.default_settings)
|
||||
|
||||
settings = LazySettings()
|
||||
|
||||
# install the translation machinery so that it is available
|
||||
from django.utils import translation
|
||||
translation.install()
|
||||
|
||||
|
|
|
@ -327,14 +327,18 @@ def get_digit(value, arg):
|
|||
# DATES #
|
||||
###################
|
||||
|
||||
def date(value, arg=settings.DATE_FORMAT):
|
||||
def date(value, arg=None):
|
||||
"Formats a date according to the given format"
|
||||
from django.utils.dateformat import format
|
||||
if arg is None:
|
||||
arg = settings.DATE_FORMAT
|
||||
return format(value, arg)
|
||||
|
||||
def time(value, arg=settings.TIME_FORMAT):
|
||||
def time(value, arg=None):
|
||||
"Formats a time according to the given format"
|
||||
from django.utils.dateformat import time_format
|
||||
if arg is None:
|
||||
arg = settings.TIME_FORMAT
|
||||
return time_format(value, arg)
|
||||
|
||||
def timesince(value):
|
||||
|
@ -435,7 +439,7 @@ def pprint(value):
|
|||
return pformat(value)
|
||||
except Exception, e:
|
||||
return "Error in formatting:%s" % e
|
||||
|
||||
|
||||
# Syntax: register.filter(name of filter, callback)
|
||||
register.filter(add)
|
||||
register.filter(addslashes)
|
||||
|
|
|
@ -117,9 +117,12 @@ def translation(language):
|
|||
|
||||
globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale')
|
||||
|
||||
parts = settings.SETTINGS_MODULE.split('.')
|
||||
project = __import__(parts[0], {}, {}, [])
|
||||
projectpath = os.path.join(os.path.dirname(project.__file__), 'locale')
|
||||
if settings.SETTINGS_MODULE is not None:
|
||||
parts = settings.SETTINGS_MODULE.split('.')
|
||||
project = __import__(parts[0], {}, {}, [])
|
||||
projectpath = os.path.join(os.path.dirname(project.__file__), 'locale')
|
||||
else:
|
||||
projectpath = None
|
||||
|
||||
def _fetch(lang, fallback=None):
|
||||
|
||||
|
@ -155,7 +158,7 @@ def translation(language):
|
|||
if os.path.isdir(localepath):
|
||||
res = _merge(localepath)
|
||||
|
||||
if os.path.isdir(projectpath):
|
||||
if projectpath and os.path.isdir(projectpath):
|
||||
res = _merge(projectpath)
|
||||
|
||||
for appname in settings.INSTALLED_APPS:
|
||||
|
|
|
@ -540,6 +540,17 @@ you can override base translations in your project path. Or, you can just build
|
|||
a big project out of several apps and put all translations into one big project
|
||||
message file. The choice is yours.
|
||||
|
||||
.. note::
|
||||
|
||||
If you're using manually configured settings, as described in the
|
||||
`settings documentation`_, the ``locale`` directory in the project
|
||||
directory will not be examined, since Django loses the ability to work out
|
||||
the location of the project directory. (Django normally uses the location
|
||||
of the settings file to determine this, and a settings file doesn't exist
|
||||
if you're manually configuring your settings.)
|
||||
|
||||
.. _settings documentation: http://www.djangoproject.com/documentation/settings/#using-settings-without-the-django-settings-module-environment-variable
|
||||
|
||||
All message file repositories are structured the same way. They are:
|
||||
|
||||
* ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
|
||||
|
|
|
@ -724,3 +724,70 @@ Django apps. Just follow these conventions:
|
|||
* For settings that are sequences, use tuples instead of lists. This is
|
||||
purely for performance.
|
||||
* Don't reinvent an already-existing setting.
|
||||
|
||||
Using settings without setting DJANGO_SETTINGS_MODULE
|
||||
=====================================================
|
||||
|
||||
In some cases, you might want to bypass the ``DJANGO_SETTINGS_MODULE``
|
||||
environment variable. For example, if you're using the template system by
|
||||
itself, you likely don't want to have to set up an environment variable
|
||||
pointing to a settings module.
|
||||
|
||||
In these cases, you can configure Django's settings manually. Do this by
|
||||
calling ``django.conf.settings.configure()``.
|
||||
|
||||
Example::
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
settings.configure(DEBUG=True, TEMPLATE_DEBUG=True,
|
||||
TEMPLATE_DIRS=('/home/web-apps/myapp', '/home/web-apps/base'))
|
||||
|
||||
Pass ``configure()`` as many keyword arguments as you'd like, with each keyword
|
||||
argument representing a setting and its value. Each argument name should be all
|
||||
uppercase, with the same name as the settings described above. If a particular
|
||||
setting is not passed to ``configure()`` and is needed at some later point,
|
||||
Django will use the default setting value.
|
||||
|
||||
Custom default settings
|
||||
-----------------------
|
||||
|
||||
If you'd like default values to come from somewhere other than
|
||||
``django.conf.global_settings``, you can pass in a module or class that
|
||||
provides the default settings as the ``default_settings`` argument (or as the
|
||||
first positional argument) in the call to ``configure()``.
|
||||
|
||||
In this example, default settings are taken from ``myapp_defaults``, and the
|
||||
``DEBUG`` setting is set to ``True``, regardless of its value in
|
||||
``myapp_defaults``::
|
||||
|
||||
from django.conf import settings
|
||||
from myapp import myapp_defaults
|
||||
|
||||
settings.configure(default_settings=myapp_defaults, DEBUG=True)
|
||||
|
||||
The following example, which uses ``myapp_defaults`` as a positional argument,
|
||||
is equivalent::
|
||||
|
||||
settings.configure(myapp_defaults, DEBUG = True)
|
||||
|
||||
Either configure() or DJANGO_SETTINGS_MODULE is required
|
||||
--------------------------------------------------------
|
||||
|
||||
If you're not setting the ``DJANGO_SETTINGS_MODULE`` environment variable, you
|
||||
*must* call ``configure()`` at some point before using any code that reads
|
||||
settings.
|
||||
|
||||
If you don't set ``DJANGO_SETTINGS_MODULE`` and don't call ``configure()``,
|
||||
Django will raise an ``EnvironmentError`` exception the first time a setting
|
||||
is accessed.
|
||||
|
||||
If you set ``DJANGO_SETTINGS_MODULE``, access settings values somehow, *then*
|
||||
call ``configure()``, Django will raise an ``EnvironmentError`` saying settings
|
||||
have already been configured.
|
||||
|
||||
Also, it's an error to call ``configure()`` more than once, or to call
|
||||
``configure()`` after any setting has been accessed.
|
||||
|
||||
It boils down to this: Use exactly one of either ``configure()`` or
|
||||
``DJANGO_SETTINGS_MODULE``. Not both, and not neither.
|
||||
|
|
|
@ -7,6 +7,10 @@ perspective -- how it works and how to extend it. If you're just looking for
|
|||
reference on the language syntax, see
|
||||
`The Django template language: For template authors`_.
|
||||
|
||||
If you're looking to use the Django template system as part of another
|
||||
application -- i.e., without the rest of the framework -- make sure to read
|
||||
the `configuration`_ section later in this document.
|
||||
|
||||
.. _`The Django template language: For template authors`: http://www.djangoproject.com/documentation/templates/
|
||||
|
||||
Basics
|
||||
|
@ -876,3 +880,37 @@ The only new concept here is the ``self.nodelist.render(context)`` in
|
|||
For more examples of complex rendering, see the source code for ``{% if %}``,
|
||||
``{% for %}``, ``{% ifequal %}`` and ``{% ifchanged %}``. They live in
|
||||
``django/template/defaulttags.py``.
|
||||
|
||||
.. _configuration:
|
||||
|
||||
Configuring the template system in standalone mode
|
||||
==================================================
|
||||
|
||||
.. note::
|
||||
|
||||
This section is only of interest to people trying to use the template
|
||||
system as an output component in another application. If you are using the
|
||||
template system as part of a Django application, nothing here applies to
|
||||
you.
|
||||
|
||||
Normally, Django will load all the configuration information it needs from its
|
||||
own default configuration file, combined with the settings in the module given
|
||||
in the ``DJANGO_SETTINGS_MODULE`` environment variable. But if you're using the
|
||||
template system independently of the rest of Django, the environment variable
|
||||
approach isn't very convenient, because you probably want to configure the
|
||||
template system in line with the rest of your application rather than dealing
|
||||
with settings files and pointing to them via environment variables.
|
||||
|
||||
To solve this problem, you need to use the manual configuration option
|
||||
described in the `settings file`_ documentation. Simply import the appropriate
|
||||
pieces of the templating system and then, *before* you call any of the
|
||||
templating functions, call ``django.conf.settings.configure()`` with any
|
||||
settings you wish to specify. You might want to consider setting at least
|
||||
``TEMPLATE_DIRS`` (if you are going to use template loaders),
|
||||
``DEFAULT_CHARSET`` (although the default of ``utf-8`` is probably fine) and
|
||||
``TEMPLATE_DEBUG``. All available settings are described in the
|
||||
`settings documentation`_, and any setting starting with *TEMPLATE_*
|
||||
is of obvious interest.
|
||||
|
||||
.. _settings file: http://www.djangoproject.com/documentation/settings/#using-settings-without-the-django-settings-module-environment-variable
|
||||
.. _settings documentation: http://www.djangoproject.com/documentation/settings/
|
||||
|
|
|
@ -507,4 +507,5 @@ def run_tests(verbosity=0, standalone=False):
|
|||
raise Exception, msg
|
||||
|
||||
if __name__ == "__main__":
|
||||
settings.configure()
|
||||
run_tests(1, True)
|
||||
|
|
|
@ -73,6 +73,10 @@ class TestRunner:
|
|||
def run_tests(self):
|
||||
from django.conf import settings
|
||||
|
||||
# An empty access of the settings to force the default options to be
|
||||
# installed prior to assigning to them.
|
||||
settings.INSTALLED_APPS
|
||||
|
||||
# Manually set INSTALLED_APPS to point to the test models.
|
||||
settings.INSTALLED_APPS = [MODEL_TESTS_DIR_NAME + '.' + a for a in get_test_models()]
|
||||
|
||||
|
|
Loading…
Reference in New Issue