Metadata-Version: 2.3
Name: dj-toml-settings
Version: 0.6.0
Summary: Load Django settings from a TOML file
Keywords: django,web,toml
Author: Adam Hill
Author-email: Adam Hill <adam@adamghill.com>
License: The MIT License (MIT)
         
         Copyright (c) 2020 Ceterai
         Copyright (c) 2025 adamghill
         
         Permission is hereby granted, free of charge, to any person obtaining a copy of
         this software and associated documentation files (the "Software"), to deal in
         the Software without restriction, including without limitation the rights to
         use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
         the Software, and to permit persons to whom the Software is furnished to do so,
         subject to the following conditions:
         
         The above copyright notice and this permission notice shall be included in all
         copies or substantial portions of the Software.
         
         THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
         FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
         COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
         IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
         CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: Django
Classifier: Framework :: Django :: 3
Classifier: Framework :: Django :: 4
Classifier: Framework :: Django :: 5
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3.15
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Dist: dj-typed-settings>=0.3.1
Requires-Dist: python-dateutil>=2.9.0.post0
Requires-Dist: tomli>=1.1.0 ; python_full_version < '3.11'
Requires-Dist: typeguard>=2
Requires-Python: >=3.10
Project-URL: Homepage, https://github.com/adamghill/dj-toml-settings/
Project-URL: Repository, https://github.com/adamghill/dj-toml-settings.git
Description-Content-Type: text/markdown

# dj-toml-settings ⚙️

> Load Django settings from a TOML file

`dj-toml-settings` reads settings from a TOML file. By default, both `pyproject.toml` and `django.toml` files are parsed for settings in the `[tool.django]` namespace.

```toml
[tool.django]

# Paths are relative to the TOML file (unless they are absolute)
BASE_DIR = { "$path" = "." }
STATIC_ROOT = { "$path" = "staticfiles" }

# This sets the key based on the environment variable
SECRET_KEY = { "$env" = "SECRET_KEY" }

# This sets the key based on the environment variable, but has a fallback
ADMIN_URL_PATH = { "$env" = "ADMIN_URL_PATH", "$default"="admin" }

# Booleans, arrays, tables (dictionaries), integers, strings, floats, dates are all supported in TOML
DEBUG = true
ALLOWED_HOSTS = [
  "127.0.0.1",
]

# Values can be cast to a bool, int, str, float, decimal, datetime, date, time, timedelta, url, Path
SITE_ID = { "$int" = "1" }
SITE_ID = { "$value" = "1", "$type" = "int" }  # This is equivalent to the previous line

# Database and cache URLs can be parsed and converted to typical Django dictionary settings
DATABASES = { default = { "$db" = "postgres://user:pass@localhost:5432/dbname" } }
CACHES = { default = { "$cache" = "redis://127.0.0.1:6379/1" } }

# This is an implicit dictionary and equivalent to `COLTRANE = { TITLE = "Example blog" }`
[tool.django.COLTRANE]
TITLE = "Example blog"

# Any name can be used under the `apps` namespace to organize settings
[tool.django.apps.tailwind-cli]
TAILWIND_CLI_USE_DAISY_UI = true
TAILWIND_CLI_SRC_CSS = ".django_tailwind_cli/source.css"

# The `envs` namespace can be used for environment-specific settings, e.g. these settings are included when the `ENVIRONMENT` environment variable is "development"
[tool.django.envs.development]
ALLOWED_HOSTS = { "$insert" = "example.localhost" }

# These settings would be included when the `ENVIRONMENT` environment variable is "production"
[tool.django.envs.production]
DEBUG = false
ALLOWED_HOSTS = { "$insert" = "example.com" }
```

## Features 🤩

### Variables

Use `${SOME_VARIABLE_NAME}` to use an existing setting as a value.

```toml
[tool.django]
GOOD_IPS = ["127.0.0.1"]
ALLOWED_HOSTS = "${GOOD_IPS}"  # note: this needs to be quoted as a string to be valid TOML, but will be converted into a `list`
```

### Apps

`[tool.django.apps.{ANY_NAME_HERE}]` sections of the TOML file can be used to group settings together. They can be named anything. They will override any settings in `[tool.django]`.

```toml
[tool.django.apps.tailwind-cli]
TAILWIND_CLI_USE_DAISY_UI = true
TAILWIND_CLI_SRC_CSS = ".django_tailwind_cli/source.css"
```

### Environments

The `[tool.django.envs.{ENVIRONMENT_NAME}]` section of the TOML file will be used when `{ENVIRONMENT_NAME}` is set to the `ENVIRONMENT` environment variable. For example, `ENVIRONMENT=production python manage.py runserver` will load all settings in the `[tool.django.envs.production]` section. There settings will override any settings in `[tool.django.apps.*]` or `[tool.django]`.

```toml
[tool.django]
ALLOWED_HOSTS = ["127.0.0.1"]

[tool.django.envs.development]
ALLOWED_HOSTS = ["example.localhost"]

[tool.django.envs.production]
ALLOWED_HOSTS = ["example.com"]
```

## Special operations 😎

By default, special operations are denoted by an [`inline table`](https://toml.io/en/v1.0.0#inline-table), (aka a `dictionary`) with a key that starts with a `$`, e.g. `{ "$value" = "1" }`.

### Path

Converts a string to a `Path` object by using a `$path` key. Handles relative paths based on the location of the parsed TOML file.

```toml
[tool.django]
BASE_DIR = { "$path" = "." }
PROJECT_DIR = { "$path" = "./your_project_folder" }
REPOSITORY_DIR = { "$path" = "./.." }
```

### Environment Variable

Retrieve variables from the environment by using an `$env` key. Specify an optional `$default` key for a fallback value.

```toml
[tool.django]
EMAIL_HOST_PASSWORD = { "$env" = "SECRET_PASSWORD" }
SECRET_KEY = { "$env" = "SECRET_KEY", "$default" = "this-is-a-secret" }
```

### Arrays

Add items to an array by using the `$insert` key.

```toml
[tool.django]
ALLOWED_HOSTS = { "$insert" = "127.0.0.1" }
```

Specify the index of the new item with the `$index` key.

```toml
[tool.django]
ALLOWED_HOSTS = { "$insert" = "127.0.0.1", "$index" = 0 }
```

#### Integer Access
 
Modify specific elements of an array by using numeric sub-keys. This is particularly useful for overriding individual items in a list from different sections (like `envs`).
 
```toml
[tool.django.TEMPLATES.0]
BACKEND = "django.template.backends.django.DjangoTemplates"
DIRS = []
APP_DIRS = true
```
 
If the array already exists, the specified index will be updated. If it does not exist, a new array will be created with the specified values.
 
Operators now work at any depth, which is especially useful for nested Django settings like `DATABASES` or `CACHES`.

```toml
[tool.django.DATABASES.default]
# This will insert an option into the existing default database configuration
OPTIONS = { "$insert" = "some_option" }
```

### None

Specify `None` for a variable with a `$none` key. The value must be truthy, i.e. `true` or 1 (even though the value won't get used).

```toml
[tool.django]
EMAIL_HOST_PASSWORD = { "$none" = 1 }
```

### Value

Specifies a value for a variable.

```toml
[tool.django]
SITE_ID = { "$value" = 1 }
```

Two styles are supported for parsing database and cache URLs: **special** and **cast**.

**Special**

Use the `$db` or `$cache` operator.

```toml
[tool.django]
DATABASES = { default = { "$db" = "postgres://user:pass@localhost:5432/dbname" } }
CACHES = { default = { "$cache" = "redis://127.0.0.1:6379/1" } }
```

**Cast**

Use `$value` and `$type` (useful when combining with other operators like `$env`).

```toml
[tool.django]
DATABASES = { default = { "$value" = "sqlite:///:memory:", "$type" = "db" } }

# Combining with environment variables
CACHES = { default = { "$env" = "REDIS_URL", "$type" = "cache" } }
```

`$type` can be used as an additional operator with any other operator.

```toml
[tool.django]
SITE_ID = { "$env" = "SITE_ID", $type = "int" }
```

```toml
[tool.django]
SITE_ID = { "$value" = "1", $type = "int" }
```

## Example Integrations 💚

### Django

This will override any variables defined in `settings.py` with settings from the TOML files.

```python
# settings.py
from dj_toml_settings import configure_toml_settings

...

configure_toml_settings(data=globals())
```

### [nanodjango](https://nanodjango.readthedocs.io) 

```python
# app.py
from pathlib import Path
from dj_toml_settings import get_toml_settings

base_dir = Path(__file__).resolve().parent
app = Django(**get_toml_settings(base_dir=base_dir))

...
```

### [coltrane](https://coltrane.adamghill.com)

```python
# app.py
from pathlib import Path
from django.core.management import execute_from_command_line
from dj_toml_settings import get_toml_settings
from coltrane import initialize

base_dir = Path(__file__).resolve().parent.parent
wsgi = initialize(**get_toml_settings(base_dir=base_dir))

if __name__ == "__main__":
    execute_from_command_line()

...
```

## Precedence 🔻

This is the order that files and sections are parsed (by default). The later sections override the previous settings.

1. `pyproject.toml` -> `[tool.django]`
2. `pyproject.toml` -> `[tool.django.apps.*]`
3. `pyproject.toml` -> `[tool.django.envs.*]` that match `ENVIRONMENT` environment variable
4. `django.toml` -> `[tool.django]`
5. `django.toml` -> `[tool.django.apps.*]`
6. `django.toml` -> `[tool.django.envs.*]` that match `ENVIRONMENT` environment variable

## Specify a TOML file 🤓

```python
from pathlib import Path
from dj_toml_settings import get_toml_settings

base_dir = Path(__file__).resolve().parent
toml_settings = get_toml_settings(base_dir=base_dir, toml_settings_files=["custom-settings.toml"])
...
```

## Test 🧪

- `uv install pip install -e .[dev]`
- `just test`

## Inspiration 😍

- [django-pyproject](https://github.com/Ceterai/django-pyproject)
- [django-settings-toml](https://github.com/maxking/django-settings-toml)
