New organization of settings

Only one setting is now available from the environment:
DJANGO_CONFIG_FILE, it gives a path to a Python that will be executed at
the end of the settings module.

For simpler usage this environment is set by passerelle_manage.py by
passing it a new mandatory option '--config=/path/to/config'.

Tenant settings are now activated by passing the '--multitenant' flag to
passerelle_manage.py.

All OS platform specific paths have been removed, it's expected that
packaging will add them. Debian for example would provide a
debian_config.py file to adapt to its own paths.
This commit is contained in:
Benjamin Dauvergne 2014-10-02 09:54:39 +02:00 committed by Thomas NOEL
parent 8259879114
commit 5dbf5387b8
6 changed files with 263 additions and 281 deletions

29
README Normal file
View File

@ -0,0 +1,29 @@
Initializing the database
-------------------------
To create the database, execute the following line:
./passerelle_manage.py --config=config_example.py syncdb --migrate
The new database is created inside `passerelle.sqlite3` in the current directory.
Running
-------
The command line for starting is:
./passerelle_manage.py --config=config_example.py runserver
Passerelle is available on http://127.0.0.1:80000
Options
-------
--config=/path/to/config.py
Configuration file. MANDATORY.
--multitenant
Activate multi-tenant mode. The python-entrouvert package must be installed.

14
config_example.py Normal file
View File

@ -0,0 +1,14 @@
DEBUG = True
SECRET_KEY = 'changeme'
MEDIA_ROOT = 'media'
STATIC_ROOT = 'collected-static'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'passerelle.sqlite3',
}
}

View File

@ -0,0 +1,107 @@
# Django default settings for passerelle project.
from django.conf import global_settings
import os
import logging
try:
from logging.handlers import NullHandler
except ImportError:
# python < 2.7
class NullHandler(logging.Handler):
def emit(self, record):
pass
logging.getLogger('passerelle').addHandler(NullHandler())
PACKAGE_PATH = os.path.dirname(__file__)
LANGUAGE_CODE = 'fr-fr'
# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = True
# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/media/'
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'
# Additional locations of static files
STATICFILES_DIRS = (os.path.join(PACKAGE_PATH, 'static'),)
# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = global_settings.STATICFILES_FINDERS + ('gadjo.finders.XStaticFinder',)
MIDDLEWARE_CLASSES = global_settings.MIDDLEWARE_CLASSES + (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'passerelle.base.middleware.SearchApiUser'
)
ROOT_URLCONF = 'passerelle.urls'
# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'passerelle.wsgi.application'
LOCALE_PATHS = (os.path.join(PACKAGE_PATH, 'locale'),)
TEMPLATE_DIRS = (os.path.join(PACKAGE_PATH, 'templates'),)
TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
'django.core.context_processors.request',
'passerelle.base.context_processors.template_vars',
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'south',
'passerelle.base',
'passerelle.datasources',
'passerelle.repost',
'passerelle.messages',
'passerelle.register',
'passerelle.queue',
'clicrdv',
'gdc',
'solis',
'makorepost',
'choosit',
'oxyd',
'ovh',
'mobyt',
'pastell',
'gadjo',
)
LOGIN_REDIRECT_URL = 'homepage'
CLICRDV_SERVER = None
CLICRDV_API_KEY = None
CLICRDV_API_USERNAME = None
CLICRDV_API_PASSWORD = None
# where to find templates for makorepost objects
MAKO_TEMPLATES_DIRS = (
os.path.join(PACKAGE_PATH, 'apps', 'makorepost', 'templates.mako'),
os.path.join(PACKAGE_PATH, 'apps', 'solis', 'templates.mako'),
)
MAKO_TEMPLATES_MODULES = None # store generated Mako module files in this directory (optional)

View File

@ -1,286 +1,30 @@
# Django settings for passerelle project.
from django.conf import global_settings
from django.conf.global_settings import *
from passerelle.default_settings import *
from django.core.exceptions import ImproperlyConfigured
import os
import glob
import json
import re
import logging
DEBUG = True
TEMPLATE_DEBUG = DEBUG
DEBUG_TOOLBAR = False
if 'DJANGO_CONFIG_FILE' in os.environ:
logging.getLogger('passerelle').debug('Loading setting file %r', os.environ['DJANGO_CONFIG_FILE'])
execfile(os.environ['DJANGO_CONFIG_FILE'])
PROJECT_NAME = 'passerelle'
PROJECT_PATH = os.path.dirname(os.path.dirname(__file__))
VAR_DIR = os.environ.get('PASSERELLE_VAR_DIR', os.path.join('/var/lib', PROJECT_NAME))
ETC_DIR = os.environ.get('PASSERELLE_ETC_DIR', os.path.join('/etc', PROJECT_NAME))
if 'PASSERELLE_VAR_DIRS' in os.environ:
VAR_DIRS = os.environ['PASSERELLE_VAR_DIRS'].split(':')
else:
VAR_DIRS = (VAR_DIR,)
VAR_DIRS = (x for x in VAR_DIRS if os.path.exists(x))
if 'PASSERELLE_CONFIG_DIRS' in os.environ:
CONFIG_DIRS = os.environ['PASSERELLE_CONFIG_DIRS'].split(':')
else:
CONFIG_DIRS = (ETC_DIR,)
ADMINS = (
# ('Your Name', 'your_email@example.com'),
)
MANAGERS = ADMINS
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(PROJECT_PATH, 'passerelle.sqlite3'),
}
}
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# In a Windows environment this must be set to your system time zone.
TIME_ZONE = 'America/Chicago'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'fr-fr'
SITE_ID = 1
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True
# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = True
# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = os.path.join(PROJECT_PATH, 'media')
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/media/'
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = os.path.join(VAR_DIR, 'collected-static')
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'
# Additional locations of static files
STATICFILES_DIRS = tuple(os.path.join(var_dir, 'static') for var_dir in VAR_DIRS) + (
os.path.join(PROJECT_PATH, 'passerelle', 'static'),
)
# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = global_settings.STATICFILES_FINDERS + ('gadjo.finders.XStaticFinder',)
# Make this unique, and don't share it with anybody.
SECRET_KEY = 't!sc5(jif2k5ymm_w@@j6hfiw(xj)(mn%euj#*_cgv(&amp;cxm$q9'
# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'passerelle.base.middleware.SearchApiUser'
)
ROOT_URLCONF = 'passerelle.urls'
# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'passerelle.wsgi.application'
LOCALE_PATHS = (os.path.join(PROJECT_PATH, 'passerelle', 'locale'),)
TEMPLATE_DIRS = tuple(os.path.join(var_dir, 'templates') for var_dir in VAR_DIRS) + (
os.path.join(PROJECT_PATH, 'passerelle', 'templates'),
)
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.core.context_processors.tz',
'django.core.context_processors.request',
'django.contrib.messages.context_processors.messages',
'passerelle.base.context_processors.template_vars',
)
if 'DATABASES' not in globals():
logging.getLogger('passerelle').error('Unable to boot: You must define a DATABASES in your settings')
raise ImproperlyConfigured('You must define a DATABASES variable in your settings')
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'south',
'passerelle.base',
'passerelle.datasources',
'passerelle.repost',
'passerelle.messages',
'passerelle.register',
'passerelle.queue',
'clicrdv',
'gdc',
'solis',
'makorepost',
'choosit',
'oxyd',
'ovh',
'mobyt',
'pastell',
'gadjo',
)
# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
}
}
LOGIN_REDIRECT_URL = 'homepage'
LOGIN_URL = 'login'
LOGOUT_URL = 'logout'
CLICRDV_SERVER = None
CLICRDV_API_KEY = None
CLICRDV_API_USERNAME = None
CLICRDV_API_PASSWORD = None
# where to find templates for makorepost objects
MAKO_TEMPLATES_DIRS = (
os.path.join(PROJECT_PATH, 'passerelle', 'apps', 'makorepost', 'templates.mako'),
)
if 'solis' in INSTALLED_APPS:
MAKO_TEMPLATES_DIRS += (
os.path.join(PROJECT_PATH, 'passerelle', 'apps', 'solis', 'templates.mako'),
)
MAKO_TEMPLATES_MODULES = None # store generated Mako module files in this directory (optional)
PASSERELLE_QUEUE_AUTHORIZED_DIRECTORIES = ()
PASSERELLE_QUEUE_DEFAULT_TMP_DIRECTORY = '/var/tmp'
TENANT_BASE = None
# load user settings
def load_dict_config(d):
for key in d:
if re.match('^[A-Z][_A-Z0-9]*$', key):
globals()[key] = d[key]
for config_dir in CONFIG_DIRS:
wildcard = os.path.join(config_dir, '*.json')
for path in sorted(glob.glob(wildcard)):
json_config = json.load(file(path))
if not isinstance(json_config, dict):
raise ImproperlyConfigured('JSON file %r is not a dictionnary' % path)
load_dict_config(json_config)
for config_dir in CONFIG_DIRS:
config_py = os.path.join(config_dir, 'config.py')
if os.path.exists(config_py):
execfile(config_py, globals())
try:
from local_settings import *
except ImportError, e:
if 'local_settings' in e.args[0]:
if DEBUG:
# Load debug toolbar when available
try:
import debug_toolbar
except:
pass
TENANT_BASE = os.environ.get('TENANT_BASE', TENANT_BASE)
if TENANT_BASE:
SOUTH_TESTS_MIGRATE = False
if DATABASES['default']['ENGINE'] != 'django.db.backends.postgresql_psycopg2':
raise ImproperlyConfigured('MULTITENANT only work with a postgresql database')
DATABASES['default']['ENGINE'] = 'tenant_schemas.postgresql_backend'
TEMPLATE_LOADERS = ('entrouvert.djommon.multitenant.template_loader.FilesystemLoader',) + TEMPLATE_LOADERS
DEFAULT_FILE_STORAGE = 'entrouvert.djommon.multitenant.storage.TenantFileSystemStorage'
MIDDLEWARE_CLASSES = (
'entrouvert.djommon.multitenant.middleware.TenantMiddleware',
'entrouvert.djommon.multitenant.middleware.JSONSettingsMiddleware',
'entrouvert.djommon.multitenant.middleware.PythonSettingsMiddleware',
) + MIDDLEWARE_CLASSES
INSTALLED_APPS = INSTALLED_APPS + ('entrouvert.djommon.multitenant',)
TENANT_APPS = INSTALLED_APPS
TENANT_MODEL = 'multitenant.Tenant'
TENANT_TEMPLATE_DIRS = ( TENANT_BASE, )
SOUTH_DATABASE_ADAPTERS = {
'default': 'south.db.postgresql_psycopg2',
}
SHARED_APPS = (
'django.contrib.staticfiles',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
)
if DEBUG and DEBUG_TOOLBAR:
MIDDLEWARE_CLASSES += (
'debug_toolbar.middleware.DebugToolbarMiddleware',
)
INSTALLED_APPS += (
'debug_toolbar',
)
else:
logging.getLogger('passerelle').debug('loading debug_toolbar')
MIDDLEWARE_CLASSES += (
'debug_toolbar.middleware.DebugToolbarMiddleware',
)
INSTALLED_APPS += (
'debug_toolbar',
)

View File

@ -0,0 +1,66 @@
from django.conf.global_settings import *
from passerelle.default_settings import *
from django.core.exceptions import ImproperlyConfigured
import os
import logging
try:
import entrouvert
except ImportError:
raise ImproperlyConfigured('python-entrouvert MUST be installed for the multitenant mode to work')
SOUTH_TESTS_MIGRATE = False
TEMPLATE_LOADERS = ('entrouvert.djommon.multitenant.template_loader.FilesystemLoader',) + TEMPLATE_LOADERS
DEFAULT_FILE_STORAGE = 'entrouvert.djommon.multitenant.storage.TenantFileSystemStorage'
MIDDLEWARE_CLASSES = (
'entrouvert.djommon.multitenant.middleware.TenantMiddleware',
'entrouvert.djommon.multitenant.middleware.JSONSettingsMiddleware',
'entrouvert.djommon.multitenant.middleware.PythonSettingsMiddleware',
) + MIDDLEWARE_CLASSES
INSTALLED_APPS = INSTALLED_APPS + ('entrouvert.djommon.multitenant',)
TENANT_APPS = INSTALLED_APPS
TENANT_MODEL = 'multitenant.Tenant'
SOUTH_DATABASE_ADAPTERS = {
'default': 'south.db.postgresql_psycopg2',
}
SHARED_APPS = (
'django.contrib.staticfiles',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
)
if 'DJANGO_CONFIG_FILE' in os.environ:
logging.getLogger('passerelle').debug('Loading setting file %r', os.environ['DJANGO_CONFIG_FILE'])
execfile(os.environ['DJANGO_CONFIG_FILE'])
if 'TENANT_BASE' not in globals():
logging.getLogger('passerelle').error('Unable to boot: You must define a TENANT_BASE in your settings')
raise ImproperlyConfigured('You must define a TENANT_BASE in your settings')
if 'DATABASES' not in globals():
logging.getLogger('passerelle').error('Unable to boot: You must define a DATABASES in your settings')
raise ImproperlyConfigured('You must define a DATABASES variable in your settings')
if DATABASES['default']['ENGINE'] != 'django.db.backends.postgresql_psycopg2':
raise ImproperlyConfigured('MULTITENANT only work with a postgresql database')
DATABASES['default']['ENGINE'] = 'tenant_schemas.postgresql_backend'
if DEBUG:
# Load debug toolbar when available
try:
import debug_toolbar
except:
pass
else:
logging.getLogger('passerelle').debug('loading debug_toolbar')
MIDDLEWARE_CLASSES += (
'debug_toolbar.middleware.DebugToolbarMiddleware',
)
INSTALLED_APPS += (
'debug_toolbar',
)

View File

@ -3,8 +3,30 @@ import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "passerelle.settings")
multitenant = False
config_file = False
for i, arg in enumerate(sys.argv[1:]):
if arg.startswith('-'):
if arg.startswith('--config='):
config_file = arg.split('=')[1]
elif arg == '--multitenant':
multitenant = True
else:
print >>sys.stderr, 'ERR: Unsupported flag', arg
sys.exit(1)
else:
break
if not config_file:
print >>sys.stderr, 'ERR: No configuration file specified, use --config=/path/to/config.py'
sys.exit(1)
os.environ['DJANGO_CONFIG_FILE'] = config_file
if multitenant:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "passerelle.tenant_settings")
else:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "passerelle.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
execute_from_command_line(sys.argv[:1] + sys.argv[i+1:])