Metadata-Version: 2.4
Name: django-nublado-core
Version: 0.4.3
Summary: A Django app for common configuration, utilities, and base models.
Author: C Nublado
License-Expression: BSD-3-Clause
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: Django>=5.0
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-django; extra == "test"
Requires-Dist: pytest-mock; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Requires-Dist: pytest-html; extra == "test"
Requires-Dist: psycopg; extra == "test"
Dynamic: license-file

# django-nublado-core

**Common abstract models, utilities, and a simple dictionary-based app settings system for Django projects.**

## Overview

I found myself copying and pasting the same "core" app containing common abstract models, utilities, and app settings configuration in my Django projects, so I made it a reusable package.

The goal is to provide simple, reliable core building blocks without introducing unnecessary complexity. The package evolves incrementally as needs arise in my projects, and is shared for others who may find it useful.

## What’s included

- Abstract base models for common Django patterns (e.g., timestamps, UUIDs, language).

- A small utility for typed, dictionary-based application settings using dataclasses.

## Installation

Install the package from PyPI.

```bash
pip install django-nublado-core
```

Add the app to your Django project.

```python
INSTALLED_APPS = [
    ...
    "django_nublado_core",
]
```

The package provides only abstract models and utilities, and does not create database tables or migrations on its own.

## Abstract models

These core abstract models provide common fields and related functionality used across multiple models.

### `TimestampModel`

An abstract model that adds automatic timestamp fields for object creation and updates.

```python
from django.db import models

from django_nublado_core.models import TimestampModel


class Article(TimestampModel):
    title = models.CharField(max_length=200)


# Sample usage
article = Article(title="hello there")
article.save()
article.created_at
article.updated_at # refreshed on each save
```

#### Notes
- Uses timezone-aware datetimes.

**Fields:**
- `created_at`
- `updated_at`

### `UUIDModel`

An abstract model that generates a UUID for a subclassed model's primary key.

```python
from django.db import models

from django_nublado_core.models import UUIDModel


class User(UUIDModel):
    username = models.CharField(max_length=200)

# Sample usage
user = User(username="Paco")
user.save()
# Primary key is a generated UUID.
user.pk # UUID('eeb4a289-034c-4e4c-9c54-98100cca1ee7')

```

#### Notes
- The generated UUID field is set as the **primary key**.

### `LanguageModel`

An abstract model that provides a language choices
field populated by the project's language settings.


`LanguageModel` contains an inner `LanguageChoices` enum derived from `settings.LANGUAGES`.

```python
from django.db import models

from django_nublado_core.models import LanguageModel


class Article(LanguageModel):
    title = models.CharField(max_length=200)


# Sample usage
article = Article(title="hello there")
article.save()
article.language # "en"

article.LanguageChoices.EN.value # "en"
```

#### Notes
- The default language value is taken from `settings.LANGUAGE_CODE`.

- Language values are validated via `full_clean()`, but are not enforced at the database level by default. This is intentional. Database-level constraints can be added by developers in subclasses if needed.


## Application settings

This package provides a small utility for loading typed, dictionary-based application settings using Django settings and Python dataclasses.

To configure settings for an app, define three things in a module (`conf.py` or `app_settings.py` for example):

- The name of the settings dictionary
- A dictionary of default values
- A dataclass defining the exposed settings

### Defining app settings

```python
from dataclasses import dataclass

from django_nublado_core.conf.base import AppSettings

# The app's settings dict name (defined in Django settings.py)
SETTINGS_DICT_NAME = "YOUR_APP_SETTINGS"

# Default values for all exposed settings
SETTINGS_DEFAULTS = {
    "SETTING_A": "setting A",
}


@dataclass(frozen=True)
class AppData:
    SETTING_A: str


app_settings = AppSettings(
    settings_dict_name=SETTINGS_DICT_NAME,
    defaults=SETTINGS_DEFAULTS,
    cls=AppData,
)
```

### Overriding settings

In your project's `settings.py`, define a dictionary matching the configured settings name.

```python
YOUR_APP_SETTINGS = {
    "SETTING_A": "custom value",
}
```

Only keys explicitly declared on the dataclass are loaded. Unknown keys are ignored and logged as warnings.

### Usage

The resulting `app_settings` object provides typed, read-only access to your application settings.

```python
from .config import app_settings

value = app_settings.SETTING_A
```

#### Notes

- All settings must have defaults defined.
- Settings are loaded and cached at runtime.
- Unknown user-defined keys are ignored and logged.


## Testing

```bash
pytest
```

#### Notes:
- Runs all tests for the app.
- Requires `pytest-django`.
