Skip to content

Commit

Permalink
Add support for nested settings (#3)
Browse files Browse the repository at this point in the history
- Add support for nested settings by dumping the contents of `BaseSettings` and `BaseModel`
- Update README with more examples and usage information
  • Loading branch information
vsakkas authored Jul 6, 2024
1 parent 984ed74 commit 0c5d9f4
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 6 deletions.
71 changes: 70 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ poetry add django-base-settings
In your Django settings file, define a subclass of `DjangoBaseSettings`:

```python
from django_base_settings import DjangoBaseSettings

class MySiteSettings(DjangoBaseSettings):
allowed_hosts: list[str] = ["www.example.com"]
debug: bool = False
Expand All @@ -39,7 +41,74 @@ DEBUG = False
DEFAULT_FROM_EMAIL = "[email protected]"
```

Field names in `DjangoBaseSettings` are case-insensitive and can be overridden through environment variables.
### Nested Settings

For more complex configurations, you can define nested settings using Pydantic models:

```python
from pydantic import Field
from pydantic_settings import BaseSettings

from django_base_settings import DjangoBaseSettings

class CacheSettings(BaseSettings):
backend: str = Field("django.core.cache.backends.redis.RedisCache", alias="BACKEND")
location: str = Field("redis://127.0.0.1:6379/1", alias="LOCATION")

class MySiteSettings(DjangoBaseSettings):
caches: dict[str, CacheSettings] = {
"default": CacheSettings()
}

my_site_settings = MySiteSettings()
```

This configuration is equivalent to:

```python
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.redis.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
}
}
```

### Environment Variables

Fields contained within DjangoBaseSettings and BaseSettings objects can be assigned values or have their default overwritten through environment variables, providing flexibility for different deployment environments.

In this example:

```python
from django_base_settings import DjangoBaseSettings

class MySiteSettings(DjangoBaseSettings):
default_from_email: str = "[email protected]"

my_site_settings = MySiteSettings()
```

You can configure the value of default_from_email by creating an environment variable, which will overwrite the default value:

```bash
export DEFAULT_FROM_EMAIL="[email protected]"
```

You can also specify a different environment variable name:

```python
from pydantic import Field

from django_base_settings import DjangoBaseSettings

class MySiteSettings(DjangoBaseSettings):
default_from_email: str = Field("[email protected]", env="DEFAULT_EMAIL")

my_site_settings = MySiteSettings()
```

In this example, setting `DEFAULT_EMAIL` as an environment variable will override the default value of `default_from_email`.

## License

Expand Down
19 changes: 15 additions & 4 deletions django_base_settings/django_base_settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sys

from pydantic import BaseModel
from pydantic_settings import BaseSettings


Expand Down Expand Up @@ -35,10 +36,20 @@ class MySiteSettings(DjangoBaseSettings):

def __init__(self) -> None:
super().__init__()

# Get the module where this instance was created
module = sys.modules[self.__class__.__module__]

# Inject validated fields as module-level variables
for field_name, field_value in self.model_dump().items():
setattr(module, field_name.upper(), field_value)
self._inject_settings(module, self)

def _inject_settings(self, module, settings: BaseSettings) -> None:
for field_name, field_value in settings.model_dump(by_alias=True).items():
# For nested models, inject a dictionary representation
if isinstance(field_value, (BaseSettings, BaseModel)):
setattr(
module,
field_name.upper(),
field_value.model_dump(by_alias=True),
)
else:
# For regular fields, inject the value directly
setattr(module, field_name.upper(), field_value)
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "django-base-settings"
version = "1.0.0"
version = "0.2.0"
description = "Use Pydantic to enhance your Django application settings."
authors = ["vsakkas <[email protected]>"]
license = "MIT"
Expand Down

0 comments on commit 0c5d9f4

Please sign in to comment.