From 01751ad3870d4e3b9e7c998e7eaf4dc4b46b2258 Mon Sep 17 00:00:00 2001 From: Martin Castro Laminrs Date: Sun, 31 May 2026 13:32:15 +0200 Subject: [PATCH] feat: Django 4.2 LTS support + release 1.5.0 (#622) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #622 — the cross-repo Django 4.2 chain is now complete. ## What Relax this package's Django pin from `>=5.0,<7.0` to `>=4.2,<7.0`, bump the API + MCP dep constraints to their 4.2-aware floors, add a 4.2 dimension to CI, and update the README's Requirements section + classifier list to advertise 4.2. | Repo | Before | After | Released | |---|---|---|---| | `django-admin-rest-api` | `django >=5.0` | `django >=4.2` | 1.1.0 (PyPI) | | `django-admin-mcp-api` | `django >=5.0` | `django >=4.2` | 1.1.0 (PyPI) | | `django-admin-react` | `django >=5.0` | `django >=4.2` | **1.5.0 (this PR)** | Why the constraint tightens on `django-admin-mcp-api` even though its public range stays the same: the 1.0.x line pins ``django>=5.0``, so a consumer on Django 4.2 would resolve to an mcp version that refuses to install. Bumping the floor to ``>=1.1.0`` keeps the install promise honest. ## CI matrix Added a `matrix.django: ["4.2", "5.2"]` dimension; runtime install swaps Django via the venv's `pip install "django~=.0"`. Today both matrix cells run py3.12. ## README freshness While here, two doc updates aligned to the post-#631 reality: - `PRIMARY_COLOR` default is now `None` (the resolver reads `AdminSite.site_primary_color` next, falling back to the built-in `#2563eb`). The settings-block example reflects the None default. - New "Accent colour" subsection in Branding documents the full resolution order + the `site_primary_color` AdminSite-attr convention, with a worked `AcmeAdminSite` example. The "Requirements" line now reads `Django: 4.2 LTS, 5.0, 5.1, 5.2 LTS, 6.0 (and any later 6.x)` — accurate for what the wheel will actually install on. ## Verification - `poetry run pytest -q` — **61 / 61 ✓** on Django 4.2.30 - `poetry run pytest -q` — **61 / 61 ✓** on Django 5.2.14 (no regression) - `pnpm test` — **187 / 187 ✓** - `pnpm -r typecheck` ✓ - `pnpm lint` ✓ - Cross-repo install resolved end-to-end: rest-api 1.1.0 + mcp-api 1.1.0 + django 4.2.30 + this package 1.5.0 in one venv. ## Minor bump rationale `1.4.13` → `1.5.0`. New supported environment (Django 4.2 LTS) per SemVer's "additive features that broaden compatibility" guideline. Matches the symmetric 1.1.0 minor bumps on `django-admin-rest-api` and `django-admin-mcp-api`. Closes #622. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ci.yml | 19 +++++++++++++++++-- README.md | 40 ++++++++++++++++++++++++++++++++++++---- poetry.lock | 20 ++++++++++---------- pyproject.toml | 23 +++++++++++++---------- 4 files changed, 76 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7948812..4e2c283 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,8 +50,20 @@ concurrency: jobs: backend: - name: Backend (pytest) + name: Backend (pytest py${{ matrix.python }} / Django ${{ matrix.django }}) runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # Django 4.2 LTS is supported through April 2026 (#622). Add it + # alongside 5.x and 6.0 so the package keeps working for the + # majority of installed Django by deployment count. + python: ["3.12"] + django: ["4.2", "5.2"] + # 4.2 added Python 3.13 support in 4.2.16 but pip may resolve to + # an earlier 4.2.x; skip 3.13 + 4.2 conservatively. (We only + # exercise py3.12 here today; the matrix is set up for an easy + # future expansion.) steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -59,7 +71,7 @@ jobs: - name: Set up Python uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 with: - python-version: "3.12" + python-version: ${{ matrix.python }} - name: Install Poetry # Poetry is pinned to the version that generated poetry.lock (see @@ -72,6 +84,9 @@ jobs: - name: Install dependencies (locked) run: poetry install --no-interaction + - name: Pin Django to the matrix version + run: poetry run pip install "django~=${{ matrix.django }}.0" + # pytest with coverage (per pyproject `addopts`), including # tests/test_security.py. `filterwarnings = ["error"]` means a new # warning fails the run. diff --git a/README.md b/README.md index 9b42571..a9dcceb 100644 --- a/README.md +++ b/README.md @@ -155,9 +155,12 @@ DJANGO_ADMIN_REACT = { "BRAND_LOGO_URL": None, # str | None — favicon + sidebar logo; # falls back to AdminSite.site_logo. Absolute # URL or a path under your STATIC_URL. - "PRIMARY_COLOR": "#2563eb", # accent for primary buttons, links, and - # active states. Hex only (validated); - # injected as the --dar-primary CSS var, so + "PRIMARY_COLOR": None, # accent for primary buttons, links, and + # active states (#437 / #631). Hex only + # (validated). None → reads + # `site_primary_color` off your AdminSite; + # fallback default is "#2563eb". Injected + # as the --dar-primary CSS var, so # rebranding needs no React rebuild. # Auth + API mount @@ -212,10 +215,39 @@ Both values are written into the SPA index template as standard reads them at boot, so the first paint already carries the consumer's brand. No flash of the package's defaults. +#### Accent colour (`PRIMARY_COLOR` + `AdminSite.site_primary_color`) + +`PRIMARY_COLOR` defaults to `None` so a custom `AdminSite` subclass can +own the brand colour the same way it owns `site_header` / `site_logo` +(#631). Resolution order — explicit setting wins, AdminSite is the +structural default, built-in fallback last: + +1. `DJANGO_ADMIN_REACT["PRIMARY_COLOR"]` — explicit per-deployment override. +2. `.site_primary_color` — convention attribute on your + custom `AdminSite` subclass (Django has no such attribute by default; + add it as a constant alongside `site_header` / `site_logo`). +3. `"#2563eb"` — the package's last-resort fallback. + +Every layer runs through a strict hex-colour regex (`#rgb` / `#rgba` / +`#rrggbb` / `#rrggbbaa`) before being injected into the SPA's `