Yet Another Way to Keep Secret Away from Git

Just sharing a function I have create to get secret from file if it is not available in environment variable.
Feel free to try, all you need is to create a file call secrets.py in the same directory as your settings.py with all the secret variables you have.

to use it simple call SECRET_KEY = get_environ("SECRET_KEY")

and of cause the variable in your secrets.py should be named accordingly.

SECRET_KEY = "the-secret-to-your-django-project"

*Also, please please, don’t forget to gitignore your secrets.py file!

You can also define a default value or a fallback value if everything else fails.

The priority is to first try to get the value from your environment variable if it not available then it will look for the default that you set, then, secrets.py file, then fallback.

Let me know if we could improve on it.

def get_environ(key, default="", fallback="", secret_store_filename="secrets.py"):
    try:
        default = os.environ[key]
        print(f"Getting {key} from env, using '{default}'")
    except KeyError:
        if not default:
            try:
                import importlib.util
                spec = importlib.util.spec_from_file_location(
                    secret_store_filename.split(".")[0],
                    os.path.join(
                        BASE_DIR,
                        os.path.basename(BASE_DIR),
                        secret_store_filename
                    ),
                )
                module = importlib.util.module_from_spec(spec)
                sys.modules["local_settings"] = module
                spec.loader.exec_module(module)
                default = eval(f"module.{key}")
                print(
                    f"Unable to get {key} from env, using '{default}' from {secret_store_filename}"
                )
            except AttributeError:
                default = ""
                print(f"Unable to get {key} from env, using '{default}'")
            except FileNotFoundError:
                print(
                    f"trying to get {key} but no local setting found. Using => '{fallback}'"
                )
    return default

That seems pretty nice if you want to avoid adding additional packages to a project for configuration.

You might also want to check out django-environ. It functions similarly to what your code is showing and has a bunch of other features like database URL and cache URL handling.

django-environ seems pretty good too, very well featured package. This little snippet of mine is just a small workaround that I came out with to handle my secret storage problem. Of cause if I require more than that, django-environ will sure be the package that I will go for! I think the only downside for django-environ is that it’s maintenance is getting a little lax(39 pull requests and last commit was 2 years ago).