Repository navigation
feat!: upgrade code and fix get_storage_class ( compatibility django42 and django52) #36628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 25 commits
567c1ca
1a76237
ef4fc25
7e27670
5b70ad8
8ba4bb1
1075cc8
05bd1d3
03e8c83
3f30323
d9ec046
b9d27be
58ce3de
04e341d
54d3f24
1561a84
18bfa4c
a7790f2
2918ecd
df11963
a8e5621
3cc0856
8a36323
5893808
07ac8cb
9cbee76
33122fa
defa634
3f5555b
9ab0900
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,10 +8,11 @@ | |
| from django.conf import settings | ||
| from django.contrib.staticfiles.storage import staticfiles_storage | ||
| from django.core.exceptions import ObjectDoesNotExist | ||
| from django.core.files.storage import get_storage_class | ||
| from django.core.files.storage import storages | ||
| from django.utils.module_loading import import_string | ||
|
|
||
| from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers | ||
| from common.djangoapps.student.models import UserProfile | ||
| from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers | ||
|
|
||
| from ..errors import UserNotFound | ||
|
|
||
|
|
@@ -22,12 +23,42 @@ | |
|
|
||
| def get_profile_image_storage(): | ||
| """ | ||
| Configures and returns a django Storage instance that can be used | ||
| to physically locate, read and write profile images. | ||
| """ | ||
| config = settings.PROFILE_IMAGE_BACKEND | ||
| storage_class = get_storage_class(config['class']) | ||
| return storage_class(**config['options']) | ||
| Returns an instance of the configured storage backend for profile images. | ||
|
|
||
| This function prioritizes different settings in the following order to determine | ||
| which storage class to use: | ||
|
|
||
| 1. If the `PROFILE_IMAGE_BACKEND` setting is defined and includes a `'class'` key, | ||
| it uses the specified storage backend and options. | ||
| 2. If not, it checks the Django 5+ `STORAGES` setting for a named storage called | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be the highest priority option, we should also make the newest way to do things the highest priority, falling back to the older ways for compatibility. This makes it easier to read and also easier to cleanup in the future when we want to drop all the old ways of doing this. |
||
| `'profile_image'` and uses its configured backend. | ||
| 3. If that is also unavailable, it falls back to the `'default'` storage defined in `STORAGES`. | ||
| 4. Finally, if no STORAGES are configured, it uses `DEFAULT_FILE_STORAGE` (legacy setting), | ||
| or falls back to `'django.core.files.storage.FileSystemStorage'` as the last resort. | ||
|
|
||
| Returns: | ||
| An instance of the configured storage backend for handling profile images. | ||
|
|
||
| Raises: | ||
| ImportError: If the specified storage class cannot be imported. | ||
| """ | ||
| config = getattr(settings, 'PROFILE_IMAGE_BACKEND', {}) | ||
| storage_class_path = config.get('class') | ||
| options = config.get('options', {}) | ||
| if not storage_class_path: | ||
| storages_config = getattr(settings, 'STORAGES', {}) | ||
|
|
||
| if 'profile_image' in storages_config: | ||
| return storages['profile_image'] | ||
| elif 'default' in storages_config: | ||
| return storages['default'] | ||
| else: | ||
| storage_class_path = (getattr(settings, 'DEFAULT_FILE_STORAGE', None) or | ||
| 'django.core.files.storage.FileSystemStorage') | ||
| options = {} | ||
|
|
||
| storage_class = import_string(storage_class_path) | ||
|
Comment on lines
+39
to
+60
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unsure if this case could ever occur but if the contents of storage_class_path are incorrect, there could be an error which we should catch e.g
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| return storage_class(**options) | ||
|
|
||
|
|
||
| def _make_profile_image_name(username): | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Importing
storagesdirectly will break on Django versions before 5.0, where this attribute doesn't exist. Wrap this import in atry/except ImportErrorand fall back to a compatible approach (e.g., usingimport_stringor the legacyget_storage_class) for Django<5.0.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is wrong, django had the
storagesimport available in 4.2, it just drops the get_storage_class function in 5.0 which is what we're trying to fix here.