Django 6: settings that are silent no-ops (STATICFILES_STORAGE, USE_L10N, CONN_MAX_AGE)
- Dominant language
- Python
- Stars
- 30
- Forks
- 3
- Avg merge
- 9h 28m
- Merged PRs (30d)
- 42
Description
🤖 Written by Claude
Audit of `variantgrid/settings/` against Django 6.x. Three settings are written where nothing reads them, so they are silent no-ops.
## 1. `STATICFILES_STORAGE` — removed in Django 5.1
`variantgrid/settings/components/default_settings.py:724`
```python
STATICFILES_STORAGE = "django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
```
Django removed this setting in 5.1 in favour of `STORAGES`. It is not read at all, so we actually run plain `StaticFilesStorage`:
```
STORAGES: {'staticfiles': {'BACKEND': 'django.contrib.staticfiles.storage.StaticFilesStorage'}}
staticfiles storage class:
```
Physical evidence in `STATIC_ROOT` — the hashed files and manifest are fossils from before the Django 5.x upgrade, and `collectstatic` has run since without regenerating them:
| file | mtime |
|---|---|
| `sitestatic/static/leaflet/leaflet-src.45c9d38e05f8.js` (hashed) | Oct 9 2025 |
| `sitestatic/static/staticfiles.json` (manifest) | Oct 9 2025 |
| `sitestatic/static/leaflet/leaflet-src.js` (plain) | May 18 |
**Impact:** `{% static %}` emits un-hashed URLs, so there is no cache-busting on standalone assets across deploys. django-compressor bundles (`CACHE/js/output..js`) still hash themselves, so this only affects non-compressed assets — images, and any JS/CSS referenced outside a `{% compress %}` block. It is also why nothing breaks when `collectstatic` is skipped.
**Two options:**
- **Delete the line.** Zero risk, documents what actually happens today.
- **Restore manifest hashing** via `STORAGES`. This is a behaviour change, not a rename — it makes `collectstatic` mandatory on every deploy, and hard-fails on any `{% static %}` reference to a file that does not exist:
```python
STORAGES = {
"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
"staticfiles": {"BACKEND": "django.contrib.staticfiles.storage.ManifestStaticFilesStorage"},
}
```
## 2. `USE_L10N` — removed in Django 5.0
`variantgrid/settings/components/default_settings.py:199`
Localisation is unconditionally on since Django 5.0. Our value was `True`, which matches the current behaviour, so deleting the line is behaviour-neutral.
## 3. `CONN_MAX_AGE` — never a top-level setting
`variantgrid/settings/components/default_settings.py:91`
```python
CONN_MAX_AGE = 60 # Reuse DB connections
```
Django only reads `CONN_MAX_AGE` from inside `DATABASES[alias]`, never at module level:
```
top-level CONN_MAX_AGE: 60
actual connection setting: 0
```
**Persistent connections have never been enabled** — every request opens a new Postgres connection. This is not a Django 6 regression (it was never a top-level setting), but it is the same failure mode as the two above: written where nothing looks.
Fix is to move it into the `DATABASES['default']` dict at `default_settings.py:96`, ideally with `CONN_HEALTH_CHECKS` alongside it:
```python
DATABASES = {
'default': {
'ENGINE': 'psqlextra.backend',
...
'CONN_MAX_AGE': 60,
'CONN_HEALTH_CHECKS': True,
}
}
```
Worth checking this against the Celery workers before enabling — long-lived worker processes holding connections open behave differently to web requests.
## Environment drift: we cannot test what we deploy
`requirements.txt:113` pins `django==6.1`, but the dev venv has **6.0.6**. Local `manage.py check` therefore runs against a Django that still *has* the 6.1 removals, and will not warn about them.
I checked all four Django 6.1 removals by hand — **all clean, no action needed**:
- postgres aggregate `ordering=` kwarg → 0 uses
- `RemoteUserMiddleware` subclasses → 0
- `finders.find(all=...)` → 2 call sites (`snpdb/templatetags/help_tags.py:39`, `uicore/templatetags/ui_help.py:42`), neither passes `all=`
- `auth.login(request, None)` `request.user` fallback → 0
Broader venv drift also present: `django-js-reverse` 1.0.0 installed vs 0.10.2 pinned; `psycopg` 3.x pinned but not installed.
## New in Django 6.0, worth adopting
**`SECURE_CSP` / `SECURE_CSP_REPORT_ONLY`** — Django 6.0 ships CSP natively via `django.middleware.csp.ContentSecurityPolicyMiddleware`. We have no CSP today and no `django-csp` dependency. Starting in report-only mode costs nothing and gives us the violation data to build a real policy from.
`TASKS` (background tasks framework) is also new in 6.0, but we use Celery, so it is not relevant.
`manage.py check --deploy` otherwise flags only `SECURE_HSTS_SECONDS` and `SECURE_SSL_REDIRECT`, which nginx handles. The `SESSION_COOKIE_SECURE` / `CSRF_COOKIE_SECURE` / `DEBUG` warnings are just the dev env not importing `https_settings.py`.
## Minor code cleanups found along the way
- `classification/views/views_uploaded_classifications_unmapped.py:248` — `django.utils.encoding.force_text1 = django.utils.encoding.force_str` has a typo (`force_text1`), so that half of the compat shim never lands. The `smart_text` line below it works. The `# lazily have s3boto3 requirements` comment above has no import under it either.
- `library/jqgrid/jqgrid.py:572` — `isinstance(field, fields.NullBooleanField)` is a permanently-false branch. `NullBooleanField` survives only to support historical migrations.
## Suggested priority
`CONN_MAX_AGE` first — it is a live performance cost on every request. The static files one is cosmetic until someone ships a stale-cached asset.
`StringAgg` and Django 7.0 is tracked in #1736.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with variantgrid/settings/components/default_settings.py at the cited settings and compare the configured values with Django 6.1 behavior. Check requirements.txt and run the relevant manage.py checks in the pinned environment, then inspect the cited template, Celery, and static-file entry points before choosing the scope. Done means the selected no-op settings are corrected or removed, behavior is verified, and the affected checks or tests pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, postgresql, python
- Domain
- backend, databases, devops, performance, security
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100