From 6a5052e9f4113546aa9b5da017393a61f35e75b6 Mon Sep 17 00:00:00 2001 From: James Tiplady Date: Sat, 29 Jul 2023 17:35:38 +0100 Subject: [PATCH] Adding support for using a subdirectory of `MEDIA_ROOT` for file fields (#475) * Adding support for using a subdirectory of MEDIA_ROOT for file fields with CONSTANCE_FILE_ROOT setting * Improving documentation for CONSTANCE_FILE_ROOT * Updating PR branch to work with latest master --- constance/admin.py | 2 +- constance/forms.py | 3 ++- constance/settings.py | 2 ++ docs/index.rst | 10 ++++++++-- example/cheeseshop/settings.py | 15 ++++++++++++++- example/requirements.txt | 1 + 6 files changed, 28 insertions(+), 5 deletions(-) diff --git a/constance/admin.py b/constance/admin.py index f42dbcf..1b51980 100644 --- a/constance/admin.py +++ b/constance/admin.py @@ -208,4 +208,4 @@ class Config: _meta = Meta() -admin.site.register([Config], ConstanceAdmin) +admin.site.register([Config], ConstanceAdmin) \ No newline at end of file diff --git a/constance/forms.py b/constance/forms.py index 5ed30c2..378ff5f 100644 --- a/constance/forms.py +++ b/constance/forms.py @@ -1,6 +1,7 @@ import hashlib from datetime import date, datetime, time, timedelta from decimal import Decimal +from os.path import join from django import conf, forms from django.contrib import messages @@ -116,7 +117,7 @@ class ConstanceForm(forms.Form): def save(self): for file_field in self.files: file = self.cleaned_data[file_field] - self.cleaned_data[file_field] = default_storage.save(file.name, file) + self.cleaned_data[file_field] = default_storage.save(join(settings.FILE_ROOT, file.name), file) for name in settings.CONFIG: current = getattr(config, name) diff --git a/constance/settings.py b/constance/settings.py index 97ba35b..fdddd82 100644 --- a/constance/settings.py +++ b/constance/settings.py @@ -14,6 +14,8 @@ CONFIG_FIELDSETS = getattr(settings, 'CONSTANCE_CONFIG_FIELDSETS', {}) ADDITIONAL_FIELDS = getattr(settings, 'CONSTANCE_ADDITIONAL_FIELDS', {}) +FILE_ROOT = getattr(settings, 'CONSTANCE_FILE_ROOT', '') + DATABASE_CACHE_BACKEND = getattr( settings, 'CONSTANCE_DATABASE_CACHE_BACKEND', diff --git a/docs/index.rst b/docs/index.rst index c047310..c0279a5 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -132,7 +132,7 @@ Note: Use later evaluated strings instead of direct classes for the field and wi 'MY_SELECT_KEY': ('yes', 'select yes or no', 'yes_no_null_select'), } -If you want to work with files you can use this configuration: +If you want to work with images or files you can use this configuration: .. code-block:: python @@ -153,8 +153,14 @@ When used in a template you probably need to use: {% get_media_prefix as MEDIA_URL %} -Images are uploaded to MEDIA_ROOT. +Images and files are uploaded to ``MEDIA_ROOT`` by default. You can specify a subdirectory of ``MEDIA_ROOT`` to use instead by adding the ``CONSTANCE_FILE_ROOT`` setting. E.g.: +.. code-block:: python + + MEDIA_ROOT = os.path.join(BASE_DIR, 'media') + CONSTANCE_FILE_ROOT = 'constance' + +This will result in files being placed in ``media/constance`` within your ``BASE_DIR``. You can use deeper nesting in this setting (e.g. ``constance/images``) but other relative path components (e.g. ``../``) will be rejected. Ordered Fields in Django Admin ------------------------------ diff --git a/example/cheeseshop/settings.py b/example/cheeseshop/settings.py index d030f0e..6e922c9 100644 --- a/example/cheeseshop/settings.py +++ b/example/cheeseshop/settings.py @@ -99,7 +99,8 @@ CONSTANCE_ADDITIONAL_FIELDS = { } ], 'email': ('django.forms.fields.EmailField',), - 'json_field': ['cheeseshop.fields.JsonField'] + 'json_field': ['cheeseshop.fields.JsonField'], + 'image_field': ['django.forms.ImageField', {}], } CONSTANCE_CONFIG = { @@ -115,6 +116,11 @@ CONSTANCE_CONFIG = { 'Some test data for json', 'json_field', ), + 'LOGO': ( + '', + 'Logo image file', + 'image_field', + ), } CONSTANCE_CONFIG_FIELDSETS = { @@ -124,6 +130,7 @@ CONSTANCE_CONFIG_FIELDSETS = { 'OWNER_EMAIL', 'MUSICIANS', 'DATE_ESTABLISHED', + 'LOGO', ], 'Awkward test settings': ['MY_SELECT_KEY', 'MULTILINE', 'JSON_DATA'], } @@ -158,4 +165,10 @@ USE_TZ = True STATIC_URL = '/static/' +MEDIA_URL = '/media/' + +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') + +CONSTANCE_FILE_ROOT = 'constance' + DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' diff --git a/example/requirements.txt b/example/requirements.txt index a39f83c..905a71c 100644 --- a/example/requirements.txt +++ b/example/requirements.txt @@ -1,2 +1,3 @@ Django>=3.2 +Pillow pymemcache