# `mgf-django` — Django integration adapters for mgf-common consumers

[![Registry](https://img.shields.io/badge/registry-Codeberg-blue)](https://codeberg.org/magogi-admin/mgf-django)
[![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://codeberg.org/magogi-admin/mgf-django)

> **Shape:** Federation sibling of `mgf-common`. The current
> `mgf-common` pin window is shown in this package's
> [Codeberg registry](https://codeberg.org/magogi-admin/mgf-django) —
> sourced from `pyproject.toml` at release time, so this README
> can't go stale. (Per v2.6 DOC-01 / project-shape taxonomy.
> PAPER-38.)
>
> **Sibling of [`mgf-common`](https://codeberg.org/magogi-admin/mgf-common)
> under the `mgf.*` namespace.** Houses the Django-specific adapters
> that previously lived under `mgf.common.django.*` — extracted at
> mgf-common v0.31 / mgf-django v0.1 per the
> [federation split plan](https://codeberg.org/magogi-admin/mgf-common/src/branch/main/docs/release/federation_roadmap.md).

## What this provides

| Submodule | What |
|---|---|
| `mgf.django` | `MgfCommonConfig` — Django `AppConfig` that runs `mgf.common.bootstrap()` once at app-registry build. `MgfRequestIdMiddleware` + `MgfContextMiddleware` — sync-mode middleware sharing the same contextvar as `mgf.fastapi.RequestIdMiddleware` for cross-framework request-id correlation. `JsonFormatter` — no-arg wrapper for Django's `LOGGING['formatters']` `'()': '...'` factory syntax. `DjangoSettingsBridge` — read-only `BaseAppSettings` view over `django.conf.settings` (so `mgf-common explain` works for Django apps). |

Eight public names. The closed-box adapter shape: your `manage.py`,
`settings.py`, and views remain unchanged; you add one entry to
`INSTALLED_APPS` and two to `MIDDLEWARE`.

## Install

```bash
pip install mgf-django
```

Pulls in `mgf-common` + `django>=4.2` automatically.

## Quick start — typical Django settings.py addition

```python
# settings.py
INSTALLED_APPS = [
    # ... your apps ...
    "mgf.django",
]

MIDDLEWARE = [
    "mgf.django.MgfRequestIdMiddleware",  # earliest
    "mgf.django.MgfContextMiddleware",
    # ... your other middleware ...
]

LOGGING = {
    "version": 1,
    "formatters": {
        "json": {"()": "mgf.django.JsonFormatter"},
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "formatter": "json",
        },
    },
    "root": {"handlers": ["console"], "level": "INFO"},
}

# Optional — both default to None (auto-derived from package metadata)
MGF_COMMON_APP_NAME = "myapp"
MGF_COMMON_APP_VERSION = "1.0.0"
```

That's the entire integration. The `AppConfig` calls
`mgf.common.bootstrap()` once when Django boots; the middlewares
carry the per-request state; the formatter routes through the
standard mgf-common redaction + OTel correlation pipeline.

## What you get for free

- **One bootstrap call** — identity, structured logging, OTel wiring,
  crash-reporting hooks installed exactly once per process.
- **Per-request `X-Request-Id`** — generated as UUID4 if missing,
  forwarded if present. Same contextvar as `mgf.fastapi` so a
  Django-to-FastAPI internal RPC propagates the request id end-to-end.
- **`AppContext` on `request.mgf_context`** — views can read identity
  + settings without touching globals.
- **Default-on log redaction** — secret-shaped fields scrubbed by the
  formatter before any sink sees them (no per-call wrapper needed).
- **`mgf-common explain` works** — `DjangoSettingsBridge.from_django()`
  exposes a curated, typed view of `django.conf.settings` for the
  diagnostic CLI.

## App label note

The Django app label is `"mgf_django"` (Django labels can't contain
dots). **Renamed at the v0.31 sibling extraction** from `"mgf_common"`
(its name when the module lived under `mgf.common.django` in
mgf-common ≤ v0.30). Consumer config that hardcoded the old
`"mgf_common"` label MUST update — typical references are in
`AppConfig.get_app_config("mgf_common")` calls or migration table-
prefix configs.

## Documentation

- [`docs/recipes/django.md`](docs/recipes/django.md) — full walkthrough.
- [`docs/cutover/v0.1.0.md`](docs/cutover/v0.1.0.md) — maiden voyage migration story (the v0.31 split).
- [`PUBLIC_API.md`](PUBLIC_API.md) — full public surface contract.
- [`CHANGELOG.md`](CHANGELOG.md) — release history.

For the federation-wide engineering standards (DESIGN_PRINCIPLES,
ERROR_HANDLING, SECURITY, etc.) see
[`mgf-standard/docs/standards/`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/).
This sibling inherits them by reference; the standards
source-of-truth lives in mgf-common.

> **Conformance: L2** per [`mgf-standard/docs/standards/`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/). Per-rule audit ledger: [`docs/inprogress/MGF_STANDARDS_CONFORMANCE.md`](docs/inprogress/MGF_STANDARDS_CONFORMANCE.md). L2 means every federation **MUST** rule applies, evidenced by the tracker.

## Status

🚧 **Experimental** — every public name is `experimental` per AP-09.
Promotion to `stable` happens release-by-release as consumer feedback
in [`mgf-common/FEEDBACK.md`](https://codeberg.org/magogi-admin/mgf-common/src/branch/main/FEEDBACK.md)
converges. The 0.x window applies. Pin tightly:
`mgf-django = ">=0.X.0,<0.Y"`.

## Cross-references

- **Filing process for sharp edges**: open an entry on
  [`mgf-common/FEEDBACK.md`](https://codeberg.org/magogi-admin/mgf-common/src/branch/main/FEEDBACK.md)
  with `[mgf-django]` prefix, OR file directly on this repo's Issues →
  maintainer mirrors into the canonical FEEDBACK.md.
- **Federation pattern**:
  [`mgf-common/docs/design/federation.md`](https://codeberg.org/magogi-admin/mgf-common/src/branch/main/docs/design/federation.md).
- **The split that created this sibling**:
  [`mgf-common/docs/release/federation_roadmap.md`](https://codeberg.org/magogi-admin/mgf-common/src/branch/main/docs/release/federation_roadmap.md).
