| 406 | |
| 407 | === Setting Inheritance with Hierarchy === |
| 408 | |
| 409 | I need to be able to inherit from a base settings file, then for each environment provide overrides. In dev env, we need developer specific settings. The following extends [http://djangopeople.net/cordis Sergey Yushckeyev's] solution above: |
| 410 | |
| 411 | {{{settings/__init__.py}}} |
| 412 | {{{ |
| 413 | #!python |
| 414 | import os, pwd |
| 415 | |
| 416 | # certain keys we want to merge instead of copy |
| 417 | merge_keys = ('INSTALLED_APPS', 'MIDDLEWARE_CLASSES') |
| 418 | |
| 419 | def deep_update(from_dict, to_dict): |
| 420 | for (key, value) in from_dict.iteritems(): |
| 421 | if key in to_dict.keys() and isinstance(to_dict[key], dict) and isinstance(value, dict): |
| 422 | deep_update(value, to_dict[key]) |
| 423 | elif key in merge_keys: |
| 424 | if not key in to_dict: |
| 425 | to_dict[key] = () |
| 426 | to_dict[key] = to_dict[key] + from_dict[key] |
| 427 | else: |
| 428 | to_dict[key] = value |
| 429 | |
| 430 | # this should be one of prod, qa, staging, dev. default to dev for safety |
| 431 | env = os.environ.get('APP_ENV', 'dev') |
| 432 | |
| 433 | # try to load user specific settings |
| 434 | uid = pwd.getpwuid(os.getuid())[0] |
| 435 | |
| 436 | modules = ('common', env, uid) |
| 437 | current = __name__ |
| 438 | for module_name in modules: |
| 439 | try: |
| 440 | module = getattr(__import__(current, globals(), locals(), [module_name]), module_name) |
| 441 | except ImportError, e: |
| 442 | print 'ERROR: Unable to import %s configuration: %s' % (module_name, e) |
| 443 | raise |
| 444 | except AttributeError, e: |
| 445 | if env == 'dev' and module_name == uid: |
| 446 | print 'WARNING: Unable to import %s dev configuration: does %s.py exist?' % (module_name, module_name) |
| 447 | else: |
| 448 | raise |
| 449 | |
| 450 | # create a local copy of this module's settings |
| 451 | module_settings = {} |
| 452 | for setting in dir(module): |
| 453 | # all django settings are uppercase, so this ensures we |
| 454 | # are only processing setting from the dir() call |
| 455 | if setting == setting.upper(): |
| 456 | module_settings[setting] = getattr(module, setting) |
| 457 | deep_update(module_settings, locals()) |
| 458 | |
| 459 | #print locals() # for debugging |
| 460 | }}} |
| 461 | |
| 462 | Then, move {{{settings.py}}} to {{{common.py}}}. |
| 463 | |
| 464 | |
| 465 | The above defaults to {{{dev}}} env. You could pass in anything to {{{manage.py}}} via the {{{APP_ENV}}} environment variable. Common ones would be {{{prod}}}, {{{staging}}}, {{{qa}}}, etc. For each {{{APP_ENV}}}, you create a file {{{$APP_ENV.py}}}. Finally, create {{{$USER.py}}} file with overrides. Example files (excepting settings.py) below.. |
| 466 | |
| 467 | {{{dev.py}}} |
| 468 | {{{ |
| 469 | #!python |
| 470 | import os |
| 471 | |
| 472 | # cwd is settings. determine project path |
| 473 | cwd = os.path.dirname(os.path.abspath(__file__)) |
| 474 | project_path = cwd[:-9] # chop off "settings/" |
| 475 | |
| 476 | DEBUG = True |
| 477 | TEMPLATE_DEBUG = DEBUG |
| 478 | |
| 479 | TEMPLATE_DIRS = ( |
| 480 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". |
| 481 | # Always use forward slashes, even on Windows. |
| 482 | # Don't forget to use absolute paths, not relative paths. |
| 483 | |
| 484 | # project templates directory |
| 485 | '%s/templates' % ( project_path ) |
| 486 | ) |
| 487 | }}} |
| 488 | |
| 489 | {{{$USER.py}}} |
| 490 | {{{ |
| 491 | #!python |
| 492 | DATABASES = { |
| 493 | 'default': { |
| 494 | 'USER': 'me', |
| 495 | 'PASSWORD': 'i<3django', |
| 496 | } |
| 497 | } |
| 498 | |
| 499 | INSTALLED_APPS = ( |
| 500 | 'haystack', |
| 501 | ) |
| 502 | |
| 503 | HAYSTACK_CONNECTIONS = { |
| 504 | 'default': { |
| 505 | 'ENGINE': 'haystack.backends.solr_backend.SolrEngine', |
| 506 | 'URL': 'http://127.0.0.1:8983/solr' |
| 507 | }, |
| 508 | } |
| 509 | }}} |