Skip to main content

A simple Django package setting loader that utilizes dataclasses for type hinting and type checking

Project description

Django DataclassConf

PyPI - Version PyPI - Python Version License: MIT

A simple Django package setting loader that utilizes dataclasses for type hinting and type checking.

Bring modern Python typing, robust validation, and full IDE autocomplete to your Django configurations.

django-dataclassconf allows you to bind your Django settings cleanly to structured standard Python dataclasses. Powered by dacite, it automatically catches dynamic setting updates while ensuring your configuration layer stays type-safe and isolated.

But Why?

  • Fail-Fast Validation: Catch bad configuration types or missing values instantly during server startup or container deployment rather than hitting silent runtime crashes mid-request.

  • Full IDE Autocomplete: Say goodbye to blind getattr(settings, "MY_SETTING") calls. Enjoy full hovering type definitions and autocompletion in VS Code, PyCharm, and MyPy.

  • Dual Format Normalization: Merges flat environment styles (PREFIX_TIMEOUT = 30) and structured dictionary blocks (PREFIX = {"TIMEOUT": 30}) into a single unified object seamlessly.

  • Test-Safe Isolation: Fully supports Django's test suite cycles. When settings are overridden dynamically in unit tests, your dataclasses mutate cleanly in-place and revert automatically.

Usage

1. Define Your Configuration Dataclass

Create a file named config.py (or any name you prefer tbh) within your application or package. Inherit from BaseConfig and define your variables.

from dataclasses import dataclass, field
from django_dataclassconf.config import BaseConfig, config_loader

@dataclass
class MyPackageConfig(BaseConfig):
    DOCUMENTS_ROOT_PATH: str = '/the/default/path/'
    MAX_FILE_SIZE: int = 10000
    INDEXER_CLASS: str = 'myapp.utils.DocumentIndexer'

    @property
    def _prefix(self) -> str:
        """
        Define the config's prefix here, return blank string if it doesn't 
        have a prefix such as when we write a configuration dataclass that 
        will hold the `DEBUG` setting
        """
        return 'MY_PACKAGE'

package_config = MyPackageConfig()

2. Subscribe to the Configuration Loader

For your dataclass to grab configuration data from Django's settings.py on startup and capture updates during tests, subscribe your instance into config_loader inside your app's initialization hook:

# my_app/apps.py
class MyAppConfig(AppConfig):
    name = 'my_app'
    
    def ready(self):
        from django_dataclassconf.config import config_loader
        from .config import package_config

        config_loader.subscribe(package_config)

3. Access Your Settings Anywhere

Core Practice would be to import your configuration instance directly instead of using the global django.conf.settings object to harness the full type safety and IDE autocomplete.

# my_app/views.py
from django.http import HttpResponse
from my_app.config import package_config

def my_view(request):
    ...
    # Your IDE now natively autocompletes these fields
    if file_size > package_config.MAX_FILE_SIZE:
        return HttpResponse(
            {'detail': 'File size has exceeded the maximum size limit!'}, 
            status = 400
        )

Extras

Nested Dataclasses

Your Configuration Dataclass can also be a nested dataclasses, you only need to inherit BaseConfig to the root configuration dataclass.

from dataclasses import dataclass, field
from django_dataclassconf.conf import BaseConfig, config_loader

@dataclass
class DocumentPreview:
    preview_page_count: int = 10
    strip_cover_page: bool = False

@dataclass
class MyPackageConfig(BaseConfig):
    DOCUMENTS_ROOT_PATH: str = '/the/default/path/'
    PREVIEW: DocumentPreview = field(default_factory=DocumentPreview)

    @property
    def _prefix(self) -> str:
        return 'MY_PACKAGE'

configuration = MyPackageConfig()
config_loader.subscribe(configuration)

And it will look like this in settings.py

MY_PACKAGE = {
    'DOCUMENTS_ROOT_PATH': '/custom/path/',
    'PREVIEW': {
        'preview_page_count': 12,
        'strip_cover_page': True
    },
}

Importables

For settings that includes importing a class, instance, or function from another module, you may type-annotate them via Importable from fields.py

from django_dataclassconf.fields import Importable
import typing

from .models import Segment

@dataclass
class MyConfig(BaseConfig):
    SEGMENTER_FUNC: Importable[typing.Callable] = 'myapp.utils.segment_audio'
    SEGMENT_SERIALIZER_CLASS: Importable[typing.Type[Serializer]] = 'myapp.serializers.SegmentSerializer'
    SEGMENT_MODEL: Importable[typing.Type[Segment]] = 'myapp.Segment'

configuration = MyConfig()

And to import the expected value, call the resolve method:

# May raise an error if the provided string value is not valid 
# or if the imported value does not share the same data type as the type annotated

try:
    segment_model = configuration.SEGMENT_MODEL.resolve()

except ImportError as ie:
    print(f'Could not import SEGMENT_MODEL: {ie}')

except TypeError as te:
    print(f'Imported value has different type than expected: {te}')

License

This project is licensed under the MIT License - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_dataclassconf-0.2.0.tar.gz (11.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_dataclassconf-0.2.0-py3-none-any.whl (9.8 kB view details)

Uploaded Python 3

File details

Details for the file django_dataclassconf-0.2.0.tar.gz.

File metadata

  • Download URL: django_dataclassconf-0.2.0.tar.gz
  • Upload date:
  • Size: 11.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for django_dataclassconf-0.2.0.tar.gz
Algorithm Hash digest
SHA256 821050710a1e39e9eed685c852dfad0e8b2292394a974cf4fe942a051de94bfa
MD5 493243b1ac5c02de0ca18deb54979dc5
BLAKE2b-256 d082c6f12eb299a8566c029fe271df18969dff2f764859ae5338469e0499732a

See more details on using hashes here.

File details

Details for the file django_dataclassconf-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_dataclassconf-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 01337de82cfdcef8a3d7f3aba2665c246112cb5d2435118924bc531fa7a84ddf
MD5 53f0a191350c5e165fd97282c345cd38
BLAKE2b-256 dcc11deaa445b46c8efa1554855112d46da0a96e2104e257f4c8c3f4b4d6d679

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page