From 786fa04cb98113c617d6e7104c84ad19aa995f24 Mon Sep 17 00:00:00 2001 From: _ <50262751+hunzlahmalik@users.noreply.github.com> Date: Tue, 23 Sep 2025 17:28:24 +0500 Subject: [PATCH 1/3] feat: Upgrading storages with new dict Django52 --- registrar/settings/base.py | 11 +++++++++-- registrar/settings/devstack.py | 6 +++++- registrar/settings/production.py | 9 +++++++++ registrar/settings/test.py | 2 +- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/registrar/settings/base.py b/registrar/settings/base.py index bf24bf80e..ff4c2fb49 100644 --- a/registrar/settings/base.py +++ b/registrar/settings/base.py @@ -189,10 +189,18 @@ root('conf', 'locale'), ) +STORAGES = { + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "staticfiles": { + "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", + }, +} + # MEDIA CONFIGURATION MEDIA_ROOT = root('media') MEDIA_URL = '/api/media/' -DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' REGISTRAR_BUCKET = 'change-me-to-registrar-bucket' PROGRAM_REPORTS_BUCKET = 'change-me-to-program-reports-bucket' PROGRAM_REPORTS_FOLDER = 'reports_v2' @@ -325,7 +333,6 @@ EXTRA_APPS = [] SERVICE_USER = 'registrar_service_user' SESSION_EXPIRE_AT_BROWSER_CLOSE = False -STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage' CSRF_TRUSTED_ORIGINS = [] CACHES = { 'default': { diff --git a/registrar/settings/devstack.py b/registrar/settings/devstack.py index df0b6c0cb..f2dc3f0b5 100644 --- a/registrar/settings/devstack.py +++ b/registrar/settings/devstack.py @@ -35,7 +35,11 @@ } } -STATICFILES_STORAGE = os.environ.get('STATICFILES_STORAGE', 'django.contrib.staticfiles.storage.StaticFilesStorage') +staticfiles_storage = os.environ.get('STATICFILES_STORAGE', 'django.contrib.staticfiles.storage.StaticFilesStorage') + +if staticfiles_storage: + STORAGES["staticfiles"]["BACKEND"] = staticfiles_storage + STATIC_URL = os.environ.get('STATIC_URL', '/static/') LMS_BASE_URL = 'http://edx.devstack.lms:18000' diff --git a/registrar/settings/production.py b/registrar/settings/production.py index 3ac51fa2c..e21e70ef7 100644 --- a/registrar/settings/production.py +++ b/registrar/settings/production.py @@ -32,8 +32,17 @@ vars()[key].update(value) vars().update(config_from_yaml) + + default_file_storage = MEDIA_STORAGE_BACKEND.pop('DEFAULT_FILE_STORAGE', None) + staticfiles_storage = MEDIA_STORAGE_BACKEND.pop('STATICFILES_STORAGE', None) + vars().update(MEDIA_STORAGE_BACKEND) + if default_file_storage: + STORAGES["default"]["BACKEND"] = default_file_storage + if staticfiles_storage: + STORAGES["staticfiles"]["BACKEND"] = staticfiles_storage + DB_OVERRIDES = dict( PASSWORD=environ.get('DB_MIGRATION_PASS', DATABASES['default']['PASSWORD']), ENGINE=environ.get('DB_MIGRATION_ENGINE', DATABASES['default']['ENGINE']), diff --git a/registrar/settings/test.py b/registrar/settings/test.py index c91e5fb62..20b5d9f15 100644 --- a/registrar/settings/test.py +++ b/registrar/settings/test.py @@ -45,7 +45,7 @@ # END CELERY # Media -DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' +STORAGES["default"]["BACKEND"] = 'storages.backends.s3boto3.S3Boto3Storage' AWS_LOCATION = '' AWS_QUERYSTRING_AUTH = True AWS_QUERYSTRING_EXPIRE = 3600 From 9d1b986ca82154dd736583d2d027ef6dc2701fbc Mon Sep 17 00:00:00 2001 From: _ <50262751+hunzlahmalik@users.noreply.github.com> Date: Tue, 23 Sep 2025 20:06:28 +0500 Subject: [PATCH 2/3] fix: get_storage_class deprecated in django 52 --- registrar/apps/core/filestore.py | 19 +++++++++++++++++- registrar/apps/core/tests/test_filestore.py | 22 +++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/registrar/apps/core/filestore.py b/registrar/apps/core/filestore.py index 206616c9f..8630cf2aa 100644 --- a/registrar/apps/core/filestore.py +++ b/registrar/apps/core/filestore.py @@ -7,7 +7,8 @@ from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.core.files.base import ContentFile -from django.core.files.storage import default_storage, get_storage_class +from django.core.files.storage import default_storage +from django.utils.module_loading import import_string from registrar.apps.api.utils import to_absolute_api_url @@ -15,6 +16,22 @@ logger = logging.getLogger(__name__) +def get_storage_class(): + # Prefer new-style Django 4.2+ STORAGES + storages_config = getattr(settings, 'STORAGES', {}) + + if storages_config.get('default') and storages_config['default'].get('BACKEND'): + return import_string(storages_config['default'].get('BACKEND')) + + # Legacy fallback: DEFAULT_FILE_STORAGE + storage_class_path = getattr(settings, 'DEFAULT_FILE_STORAGE', {}) + + if storage_class_path: + return import_string(storage_class_path) + + return default_storage.__class__ + + class FilestoreBase: """ Abstract base class for file stores. diff --git a/registrar/apps/core/tests/test_filestore.py b/registrar/apps/core/tests/test_filestore.py index 2ca152492..9d492e590 100644 --- a/registrar/apps/core/tests/test_filestore.py +++ b/registrar/apps/core/tests/test_filestore.py @@ -9,7 +9,10 @@ import moto import requests from botocore.exceptions import ClientError +from django.conf import settings from django.test import TestCase +from django.test.utils import override_settings +from storages.backends.s3boto3 import S3Boto3Storage from ..filestore import ( FilestoreBase, @@ -19,6 +22,7 @@ get_filestore, get_job_results_filestore, get_program_reports_filestore, + get_storage_class, ) from ..filestore import logger as filestore_logger from .mixins import S3MockEnvVarsMixin @@ -140,3 +144,21 @@ def test_filestore_error_logging(self): assert path_prefix in log_message assert filepath in log_message assert contents not in log_message + + +class GetStorageClassTests(TestCase): + @override_settings( + STORAGES={"default": {"BACKEND": "storages.backends.s3boto3.S3Boto3Storage"}} + ) + def test_get_storage_class_with_storages(self): + storage_class = get_storage_class() + self.assertIs(storage_class, S3Boto3Storage) + + @override_settings( + DEFAULT_FILE_STORAGE="storages.backends.s3boto3.S3Boto3Storage", + STORAGES={} + ) + def test_get_storage_class_with_default_file_storage(self): + del settings.STORAGES + storage_class = get_storage_class() + self.assertIs(storage_class, S3Boto3Storage) From ecadddb16accc3b507b92253794d116018d9a65e Mon Sep 17 00:00:00 2001 From: _ <50262751+hunzlahmalik@users.noreply.github.com> Date: Thu, 2 Oct 2025 11:35:55 +0500 Subject: [PATCH 3/3] fix: update storages priority --- registrar/settings/devstack.py | 2 +- registrar/settings/production.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/registrar/settings/devstack.py b/registrar/settings/devstack.py index f2dc3f0b5..3b0191416 100644 --- a/registrar/settings/devstack.py +++ b/registrar/settings/devstack.py @@ -35,7 +35,7 @@ } } -staticfiles_storage = os.environ.get('STATICFILES_STORAGE', 'django.contrib.staticfiles.storage.StaticFilesStorage') +staticfiles_storage = os.environ.get('STATICFILES_STORAGE') if staticfiles_storage: STORAGES["staticfiles"]["BACKEND"] = staticfiles_storage diff --git a/registrar/settings/production.py b/registrar/settings/production.py index e21e70ef7..bffb3b9b4 100644 --- a/registrar/settings/production.py +++ b/registrar/settings/production.py @@ -36,13 +36,13 @@ default_file_storage = MEDIA_STORAGE_BACKEND.pop('DEFAULT_FILE_STORAGE', None) staticfiles_storage = MEDIA_STORAGE_BACKEND.pop('STATICFILES_STORAGE', None) - vars().update(MEDIA_STORAGE_BACKEND) - if default_file_storage: STORAGES["default"]["BACKEND"] = default_file_storage if staticfiles_storage: STORAGES["staticfiles"]["BACKEND"] = staticfiles_storage + vars().update(MEDIA_STORAGE_BACKEND) + DB_OVERRIDES = dict( PASSWORD=environ.get('DB_MIGRATION_PASS', DATABASES['default']['PASSWORD']), ENGINE=environ.get('DB_MIGRATION_ENGINE', DATABASES['default']['ENGINE']),