<commit_before># django-flexisettings

Several issues with the standard settings.py are solved in that project :

* get any security configuration (password, secret key, API key, etc) out of the main settings file
* support multiple environments in a flexible way

Qualities of the resulting code :

* generic, don't presume about anything concerning the project
* flexible, allow several configurations to live in the same place and easily switch between them
* simple

# Installation

* Get the source code :

```shell
$ git clone https://github.com/hrbonz/django-flexisettings.git
```

* copy the `settings/` folder to your project folder (where `settings.py`
  should be) :

```shell
$ cp -r django-flexisetttings/settings /path/to/django/myproject/
```

* copy `myproject/settings.py` in the `myproject/settings/` folder

* edit `env.py` to set the working environment, let's use `prod` here :

```shell
$ cat myproject/settings/env.py
# environment declaration
RUN_ENV = 'prod'
```

* edit `security.py` to set the `SECRET_KEY` value :

```shell
$ grep SECRET_KEY myproject/settings/security.py
SECRET_KEY = 'alongandcomplexsecretstring'
```

* set security variables in `security_prod.py` to be used in any settings file.

```shell
$ grep DEFAULTDB myproject/settings/security_prod.py
DEFAULTDB_USER = 'dbuser'
DEFAULTDB_PWD = '<PASSWORD>'
```

* edit `settings_prod.py` to override generic settings like `DATABASES`, `MEDIA_ROOT`, `TIME_ZONE`

```shell
$ cat myproject/settings/settings_prod.py
[...]
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'mydb',                      # Or path to database file if using sqlite3.
        'USER': DEFAULTDB_USER,                      # Not used with sqlite3.
        'PASSWORD': <PASSWORD>,                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}
[...]
```

# Layout

```
myproject/settings/__init__.py
                   env.py
                   security.py
                   security_RUN_ENV.py
                   settings.py
                   settings_RUN_ENV.py
```

* `__init__.py` contains all the black magic, **HERE BE DRAGONS AND
  UNICORNS**.
* `env.py` has a single variable `RUN_ENV` that defines a running
  environment. This variable is then used to call different profiles of
  configuration depending on the running environment like `dev`, `stage`
  and `prod`. The `RUN_ENV` variable can also be set by environment, the environment takes precedence over `env.py`. Example :
```shell
$ export RUN_ENV='dev'; python manage.py runserver
```
* `security.py` holds all the common security variables for the project,
  probably a good place for `SECRET_KEY`.
* `security_RUN_ENV` specific environment security variables, dedicated
  database passwords should go there. Setting defined here will override
  settings defined in `security.py`.
* `settings.py` the classic settings file found in all django projects.
* `settings_RUN_ENV.py` gathers local settings for a given running
  environment, settings defined here will override settings defined in
  `settings.py`.

# Loading order

The modules are loaded in the following order :

1. `settings`
2. `settings/env.py`
3. `settings/security.py`
4. `settings/security_RUN_ENV.py`
5. `settings/settings.py`
6. `settings/settings_RUN_ENV.py`

# Security files

A very simple way to make sure that passwords are not pushed in your VCS is to exclude any file matching `myproject/settings/security*`. It would also be a good idea to reduce the access to such files by removing read rights for users other than the one running django.

# Miscellaneous

If the `RUN_ENV` variable is false in python, the only settings files read are `security.py` and `settings.py`.

Modifying the settings does not reload the server when using `manage.py runserver`. To do so, simply use the command `touch(1)` on `settings/__init__.py` or restart the server.

Files that should not be pushed to your VCS are :

* `env.py` : to allow for multiple environments to run at the same time and avoid problems with git pulls. For this you can add `*/settings/env.py` in `.gitignore`.
* any security file : repeat after me, any security data in your VCS is a **bad idea**. For this you can add `*/settings/security*.py` in `.gitignore`.

# References

* [Django project](https://www.djangoproject.com/)
* [Django settings](https://docs.djangoproject.com/en/dev/topics/settings/)
* [Splitting up the settings file](https://code.djangoproject.com/wiki/SplitSettings)

# License

django-flexisettings is published under a 3-clause BSD license, see LICENSE.<commit_msg>Change READMe to reflect code changes<commit_after># django-flexisettings

Several issues with the standard settings.py are solved in that project :

* get any security configuration (password, secret key, API key, etc) out of the main settings file
* support multiple environments in a flexible way
* automatic discovery and configuration of common project layouts

Qualities of the resulting code :

* generic, don't presume about anything concerning the project
* flexible, allow several configurations to live in the same place and easily switch between them
* simple

# Installation

```shell
$ pip install django-flexisettings
```

# Quickstart

In development, edit `manage.py`, modify the value of `DJANGO_SETTINGS_MODULE` to point at `flexisettings.settings` and add `FLEXI_WRAPPED_MODULE` to point at you project's settings:
```
[...]
if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "flexisettings.settings")
    os.environ.setdefault("FLEXI_WRAPPED_MODULE", "myproject.settings")
[...]
```

This is all you need to get `flexisettings` to run your settings. Read further for more powerful features of `flexisettings`.

# Configuration

## `DJANGO_SETTINGS_MODULE`

Environment variable to set to point at `flexisettings.settings`

## `FLEXI_WRAPPED_MODULE`

Environment variable to set to point at your django settings, this
environment variable has to be set for `flexisettings` to work.

## `FLEXI_RUN_ENV`

String defining the running environment, used when trying to load
settings depending on the defined running environment.

## `FLEXI_SYS_PATH`

List of paths to add to `sys.path` if they exist, defaults to `['apps',
'lib']`. This will be done if `FLEXI_LAYOUT_DISCOVERY` is `True`.

## `FLEXI_LAYOUT_DISCOVERY`

Boolean that determines if `flexisettings` tries to be smart about your
project layout.

## `FLEXI_SITE_ROOT`

Path to the site root, everything that should not be tracked in a VCS
but is still part of your website. For example, the `MEDIA_ROOT` folder
should reside in the site root.

## `FLEXI_PROJECT_ROOT`

Path to the django project, basically everything that should be tracked
in a VCS.


# Example configuration

* edit `env.py` to set the working environment, let's use `prod` here :

```shell
$ cat myproject/env.py
# environment declaration
FLEXI_RUN_ENV = 'prod'
```

* edit `security.py` to set the `SECRET_KEY` value :

```shell
$ grep SECRET_KEY myproject/security.py
SECRET_KEY = 'alongandcomplexsecretstring'
```

* set security variables in `security_prod.py` to be used in any settings file.

```shell
$ grep DEFAULTDB myproject/security_prod.py
DEFAULTDB_NAME = 'dbname'
DEFAULTDB_USER = 'dbuser'
DEFAULTDB_PWD = '<PASSWORD>'
```

* edit `settings_prod.py` to override generic settings like `DATABASES`, `MEDIA_ROOT`, `TIME_ZONE`

```shell
$ cat myproject/settings/settings_prod.py
[...]
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': DEFAULTDB_NAME,
        'USER': DEFAULTDB_USER,
        'PASSWORD': <PASSWORD>,
        'HOST': '',
        'PORT': '',
    }
}
[...]
```

# Layout

```
myproject/__init__.py
          env.py
          security.py
          security_RUN_ENV.py
          settings.py
          settings_RUN_ENV.py
```

* `env.py` has a single variable `FLEXI_RUN_ENV` that defines a running
  environment. This variable is then used to call different profiles of
  configuration depending on the running environment like `dev`, `stage`
  and `prod`. The `FLEXI_RUN_ENV` variable can also be set by
  environment, the environment takes precedence over `env.py`. Example :
```shell
$ export FLEXI_RUN_ENV='dev'; python manage.py runserver
```
* `security.py` holds all the common security variables for the project,
  probably a good place for `SECRET_KEY`.
* `security_RUN_ENV` specific environment security variables, dedicated
  database passwords should go there. Setting defined here will override
  settings defined in `security.py`.
* `settings.py` the classic settings file found in all django projects.
* `settings_RUN_ENV.py` gathers local settings for a given running
  environment, settings defined here will override settings defined in
  `settings.py`.

# Loading order

The modules are loaded in the following order :

1. `myproject/env.py`
2. `myproject/security.py`
3. `myproject/security_RUN_ENV.py`
4. `myproject/settings.py`
5. `myproject/settings_RUN_ENV.py`

# Security files

A very simple way to make sure that passwords are not pushed in your VCS
is to exclude any file matching `myproject/security*`. It would also be
a good idea to reduce the access to such files by removing read rights
for users other than the one running django.

# Miscellaneous

If the `FLEXI_RUN_ENV` variable is false in python, the only settings files read are `security.py` and `settings.py`.

Modifying the settings does not reload the server when using `manage.py runserver`.

Files that should not be pushed to your VCS are :

* `env.py` : to allow for multiple environments to run at the same time
* and avoid problems with git pulls. For this you can add `myproject/env.py` in `.gitignore`.
* any security file : repeat after me, any security data in your VCS is
* a **bad idea**. For this you can add `myproject/security*.py` in `.gitignore`.

# References

* [Django project](https://www.djangoproject.com/)
* [Django settings](https://docs.djangoproject.com/en/dev/topics/settings/)
* [Splitting up the settings file](https://code.djangoproject.com/wiki/SplitSettings)

## Project layouts

* [Django Project Conventions, Revisited](http://zacharyvoase.com/2010/02/03/django-project-conventions/) (Zachary Voase)
* [django-resusable-app](http://django-reusable-app-docs.readthedocs.org/en/latest/index.html)
* [pinax-project-zero](https://github.com/pinax/pinax-project-zero)
* [Django Project Structure](http://www.deploydjango.com/django_project_structure/)
* [A general django project structure or folder layout](http://timmyomahony.com/blog/2012/11/09/general-django-project-structure-or-folder-layout/)

# License

django-flexisettings is published under a 3-clause BSD license, see LICENSE.
{'fraction_non_alphanumeric': 0.09724238026124818, 'fraction_numerical': 0.003537735849056604, 'mean_word_length': 3.9864314789687922, 'pattern_counts': {'":': 1, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 8, 'lorem ipsum': 0, 'www.': 3, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '153624', 'n_tokens_mistral': 3338, 'n_tokens_neox': 3186, 'n_words': 1222}