You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: stockage des médias en PostgreSQL (alternative au S3) (#482)
* feat: add PostgreSQL database storage backend for media files
Add a new `db_storage` app that provides a custom Django Storage backend
storing files directly in PostgreSQL. This offers a persistent storage
alternative for PaaS deployments (Scalingo, Heroku, etc.) where the
filesystem is ephemeral and S3 is not available.
Activated via SF_USE_DB_STORAGE=1. Priority: S3 > DB Storage > FileSystem.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add S3 to database storage migration command
Adds `migrate_s3_to_db` management command that:
- Downloads all files from S3 bucket and stores them as StoredFile entries
- Updates hardcoded S3 URLs in Wagtail Revision content_json
- Scans URLField/CharField and RichTextField on all models for S3 URLs
- Supports --dry-run, --skip-files, and --skip-urls options
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add DB storage documentation and update README
Add comprehensive documentation for the PostgreSQL media storage feature
including activation guide, S3 migration steps, and architecture overview.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve ruff E501 and black formatting issues
Fix line length violations (>119 chars) in test_migrate_s3.py by
extracting S3 env dict to module constant. Remove unused imports
and fix black formatting in migrate_s3_to_db.py.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove unused BytesIO import in storage.py
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: conditionner db_storage app et URL à SF_USE_DB_STORAGE
L'app db_storage et sa route /db-storage/ ne sont ajoutées que si
SF_USE_DB_STORAGE=True, suivant le même pattern que SF_USE_WHITENOISE
et PROCONNECT_ACTIVATED.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: ruff F405 noqa in settings_test, revert getattr MEDIA_ROOT
- Add noqa: F405 for INSTALLED_APPS references from star import
- Revert getattr(settings, "MEDIA_ROOT", "") to settings.MEDIA_ROOT
since Django provides a default empty string in global_settings
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add 1 GB disclaimer and DB-to-S3 reverse migration
- Add warning that DB storage is not recommended beyond 1 GB of media
in settings.py, .env.example, and docs/db-storage.md
- Add migrate_db_to_s3 management command to transfer stored files
from PostgreSQL back to an S3 bucket (with --dry-run support and
skip-if-exists logic)
- Add 5 tests for the new command
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: apply black formatting to migrate_db_to_s3 files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: clarify storage selection order and add VPS use case
Replace misleading "Priority" wording with "Selection order" to
distinguish code precedence from recommendation. Add VPS to
filesystem use cases in documentation table.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Attempt fix
* fix: handle Revision.content as JSONField in migrate_s3_to_db
Wagtail 3+ changed Revision.content_json (TextField) to
Revision.content (JSONField/dict). The previous "Attempt fix"
renamed the field but still called .replace() on a dict, which
would fail at runtime.
This fix serializes the JSON content to string for URL
search/replace, then parses back. Also adds a regression test.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix issue that prevented Images admin view to show
* Changed order of routes so that the db_storage works on a dev machine
* Allow the use of MinIO for local testing of S3
* Fix migrate_db_to_s3 command
* Necessary so that the migration script works
* Add the missing migrate_db_to_files script
* Update release number
* Update scalingo deployment file
* Updates after review
---------
Co-authored-by: Chaïb Martinez <chaibax@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
[MinIO](https://min.io/) permet de simuler un stockage objet compatible S3 en local, utile pour tester la configuration de production sans avoir besoin d'un vrai bucket S3.
119
+
120
+
#### Lancer MinIO
121
+
122
+
```sh
123
+
docker run -d \
124
+
--name minio \
125
+
-p 9000:9000 \
126
+
-p 9001:9001 \
127
+
-v ~/minio-data:/data \
128
+
-e MINIO_ROOT_USER=admin \
129
+
-e MINIO_ROOT_PASSWORD=password123 \
130
+
quay.io/minio/minio server /data --console-address ":9001"
131
+
```
132
+
133
+
#### Créer le bucket
134
+
135
+
Accéder à la console MinIO sur <http://localhost:9001> (identifiants : `admin` / `password123`), puis créer un bucket (par exemple `sc-local`).
136
+
137
+
Pour éviter l'utilisation d'URLs signées (plus simple en local), rendre le bucket public : _Buckets → sc-local → Anonymous → Add Access Rule → Prefix `/`, Access `readonly`_.
138
+
139
+
#### Variables d'environnement
140
+
141
+
Ajouter les variables suivantes dans le fichier `.env` :
142
+
143
+
```sh
144
+
S3_HOST=host.docker.internal:9000
145
+
S3_PUBLIC_HOST=localhost:9000
146
+
S3_PROTOCOL=http
147
+
S3_KEY_ID=admin
148
+
S3_KEY_SECRET=password123
149
+
S3_BUCKET_NAME=sc-local
150
+
S3_BUCKET_REGION=
151
+
S3_LOCATION=medias/
152
+
```
153
+
154
+
> **Note :** C'est la variable `S3_HOST` qui active le stockage S3 dans l'application. Sans elle, les médias seront stockés sur le système de fichiers local, quelle que soit la configuration MinIO.
155
+
156
+
Alternativement, il est également possible de passer par un stockage des fichiers directement dans la base PostgreSQL, cf. [documentation](./docs/db-storage.md)
157
+
116
158
## Fonctionnement depuis un sous-répertoire
117
159
118
160
Lorsque la variable `FORCE_SCRIPT_NAME` est configurée, le site tourne dans un sous-répertoire, fonctionnalité qui n’est pas gérée par le serveur de développement de base de Django (`runserver`).
Copy file name to clipboardExpand all lines: README.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -48,6 +48,7 @@ Sites Conformes est développé en utilisant le framework [Django](https://www.d
48
48
-**[django-dsfr](https://github.com/numerique-gouv/django-dsfr)** : Permet d’utiliser facilement le [système de design de l’État](https://www.systeme-de-design.gouv.fr/) dans des templates Django.
49
49
-**events** : Similaire à `blog`, mais permet de gérer des événements et des pages de calendrier, ainsi que les exports iCal correspondants.
50
50
-**forms** : implémentation du [module de création de formulaire](https://docs.wagtail.org/en/stable/reference/contrib/forms/index.html) de Wagtail, par exemple pour les pages de contact. Volontairement assez limité (suffisant pour un formulaire de contact mais pas beaucoup plus), pour les cas complexes il vaut mieux privilégier l’intégration de [Démarches simplifiées](https://www.demarches-simplifiees.fr) ou de [Grist](https://grist.numerique.gouv.fr/).
51
+
-**db_storage** : stockage des médias en base de données PostgreSQL, alternative au S3 pour les PaaS avec filesystem éphémère (cf. [documentation](./docs/db-storage.md))
51
52
-**proconnect** : permet la connexion via [ProConnect](https://www.proconnect.gouv.fr/)
0 commit comments