What you can try to do without modifying django code is to use custom 
settings class, which is a documented feature.

https://docs.djangoproject.com/en/1.7/topics/settings/#custom-default-settings

I'm doing that for my application, using a class that is using @property 
decorator to build dynamic settings.

I'm attaching the code that I'm currently using to use custom settings, 
this code replace the built in 
django.core.management.execute_from_command_line

What I'm doing is to create several settings that are shared across my 
django applications, and they are classes that can ineherit attributes, 
instead of being just modules.

the nice thing about this code is that you can create settings from a dict, 
from a module or from a class.

Take a look, maybe this can be a solution for your problem.






On Saturday, January 24, 2015 at 4:57:23 PM UTC+1, Marc Tamlyn wrote:
>
> I'm not sure what the benefit here would be - the settings are evaluated 
> at start up time, not on every request and the server would need to be 
> restarted for it to change.
>
> A patch to db.connections which allows the username and password to be 
> looked up on each new connection might be interesting, although I'd be 
> concerned that for any reasonably high traffic site this would be happening 
> a *lot*, normally during a user request. Something like caching it and then 
> clearing the cache when it changes upstream would be more appropriate.
>
> Marc
>
> On 24 January 2015 at 03:06, 'Andres Mejia' via Django developers 
> (Contributions to Django itself) <[email protected] 
> <javascript:>> wrote:
>
>> Hello Django devs,
>>
>> I would like to see if Django can support setting the SECRET_KEY and 
>> database creds as callables. Let me explain my situation.
>>
>> Here at Amazon, we use a system to store and fetch secrets such as a 
>> Django SECRET_KEY and database creds. There's a Python component to this 
>> system which works something like this.
>>
>> SECRET_KEY = get_creds(secret_key_id, type='privatekey')
>> . . .
>> DATABASES = {
>>     'default' = {
>>         . . .
>>         'USER': get_creds(database_creds_id, type='username'),
>>         'PASSWORD': get_creds(database_creds_id, type='password'),
>>     },
>>     . . .
>> }
>>
>> Secrets are rotated on a regular schedule or as needed. Often times the 
>> secrets are rotated without advance notice and therefore our various Django 
>> powered sites go down (because they can't connect to the database) until 
>> the web servers are restarted. We would prefer it if our web services did 
>> not have to be restarted.
>>
>> I was going to propose a patch which modifies the force_text and 
>> force_bytes methods in django.utils.encoding. The modifications basically 
>> involves adding an if statement.
>>
>> if hasattr(s, '__call__'):
>>     return s()
>>
>> This would support setting the SECRET_KEY and database creds as callables 
>> with no arguments. Example.
>>
>> SECRET_KEY = lambda: get_creds(secret_key_id, type='privatekey')
>> . . .
>> DATABASES = {
>>     'default' = {
>>         . . .
>>         'USER': lambda: get_creds(database_creds_id, type='username'),
>>         'PASSWORD': lambda: get_creds(database_creds_id, type='password'),
>>     },
>>     . . .
>> }
>>
>> My question is, should I submit a patch or might there be some other way 
>> to address my use case? Also, I'm aware of the various examples which call 
>> for storing secrets in a separate file. We cannot store secrets on the 
>> local disk (this is partly the reason for the use of the system I 
>> explained).
>>
>> -- 
>> Andres
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Django developers  (Contributions to Django itself)" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to [email protected] <javascript:>.
>> To post to this group, send email to [email protected] 
>> <javascript:>.
>> Visit this group at http://groups.google.com/group/django-developers.
>> To view this discussion on the web visit https://groups.google.com/d/
>> msgid/django-developers/54C30C4D.4030302%40amazon.com.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/0b0a2aa3-b548-4e95-a8f0-c49de4273e1f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
# -*- coding: utf-8 -*-


#!/usr/bin/env python


if __name__ == "__main__":

    from execute import execute_from_command_line
    
    execute_from_command_line(
        sys.argv,
        "settings",
        DEBUG = True
        )
# -*- coding: utf-8 -*-

class Settings(object):

    def SECRET_KEY(self):
        if self.DEBUG:
            return "abcd"
        return "12345"
# -*- coding: utf-8 -*-

class SettingsReduce(object):

    _defaults = None

    def is_overridden(self, name):
        #disable django warnings
        return not getattr(self, name) == getattr(self._defaults, name)

    @classmethod
    def to_settings(cls, *args):

        from django.utils.importlib import import_module
        from django.utils import six

        for obj in reversed(args):

            if isinstance(obj, dict):
                if obj:
                    yield type("DictSettings", (SettingsReduce, ), obj)

            elif isinstance(obj, six.string_types):
                try:
                    obj = import_module(obj)
                    try:
                        yield getattr(obj, "Settings")
                    except AttributeError:
                        yield type(
                            "ModuleSettings",
                            (SettingsReduce, ),
                            dict(
                                (f, getattr(obj, f))
                                for f in dir(obj)
                                if f.upper() == f
                                )
                            )
                except ImportError:
                    pass
            else:
                raise TypeError, "Not recognized type %s" % obj

    @classmethod
    def build(cls, name, args):
        args = tuple(cls.to_settings(*args))

        if len(args) > 0:
            return type(
                name, args, {"_defaults": args[-1]()}
                )()

        return type(name, (SettingsReduce, ), {})()


def execute(handler, *modules, **kwargs):

    from django.conf import settings
    from itertools import chain
    import os

    s = SettingsReduce.build(
        "ReducedSettings",
        chain(
            ("django.conf.global_settings", ),
            modules,
            (kwargs, )
            )
        )

    settings.configure(s)

    for key, default in (
        ("DJANGO_SETTINGS_MODULE", "settings"), #os fake env variable for django (some manage commands are hardcoding this check)
        ("CELERY_LOADER", "django"), #os env variable for celery
        ):
        if not key in os.environ:
            os.environ[key] = default

    return handler()

def execute_from_command_line(args, *modules, **kwargs):
    # Custom version of execute_from_command_line
    # it will configure the settings

    from django.core.management import execute_from_command_line as handler
    from functools import partial

    return execute(
        partial(handler, args),
        *modules,
        **kwargs
        )

def get_wsgi_application(*modules, **kwargs):
    from django.core.wsgi import get_wsgi_application as handler
    return execute(handler, *modules, **kwargs)
  • Sup... 'Andres Mejia' via Django developers (Contributions to Django itself)
    • ... Marc Tamlyn
      • ... Riccardo Di Virgilio
        • ... Riccardo Di Virgilio
          • ... 'Andres Mejia' via Django developers (Contributions to Django itself)
      • ... 'Andres Mejia' via Django developers (Contributions to Django itself)

Reply via email to