Skip to content
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

feat: Accept new STORAGES setting, introduced in Django 4.2 #1472

Merged
merged 2 commits into from
May 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ e.g::

Defaults to FileSystemStorage in ``<MEDIA_ROOT>/filer_public/`` and ``<MEDIA_ROOT>/filer_public_thumbnails/`` for public files and
``<MEDIA_ROOT>/../smedia/filer_private/`` and ``<MEDIA_ROOT>/../smedia/filer_private_thumbnails/`` for private files.
Public storage uses ``DEFAULT_FILE_STORAGE`` as default storage backend.
Public storage uses the default storage's backend. This is taken from Django's ``STORAGES``
setting if it exists or, if not, from the ``DEFAULT_FILE_STORAGE`` setting for compatibility
with earlier Django versions (5.0 or below).

``UPLOAD_TO`` is the function to generate the path relative to the storage root. The
default generates a random path like ``1d/a5/1da50fee-5003-46a1-a191-b547125053a8/filename.jpg``. This
Expand Down
2 changes: 1 addition & 1 deletion filer/admin/fileadmin.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def get_model_perms(self, request):
def display_canonical(self, instance):
canonical = instance.canonical_url
if canonical:
return mark_safe('<a href="{}">{}</a>'.format(canonical, canonical))
return mark_safe(f'<a href="{canonical}">{canonical}</a>')
else:
return '-'
display_canonical.allow_tags = True
Expand Down
8 changes: 4 additions & 4 deletions filer/admin/folderadmin.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,10 @@ def directory_listing(self, request, folder_id=None, viewtype=None):
self.get_queryset(request).get(id=last_folder_id)
except self.model.DoesNotExist:
url = reverse('admin:filer-directory_listing-root')
url = "{}{}".format(url, admin_url_params_encoded(request))
url = f"{url}{admin_url_params_encoded(request)}"
else:
url = reverse('admin:filer-directory_listing', kwargs={'folder_id': last_folder_id})
url = "{}{}".format(url, admin_url_params_encoded(request))
url = f"{url}{admin_url_params_encoded(request)}"
return HttpResponseRedirect(url)
elif folder_id is None:
folder = FolderRoot()
Expand Down Expand Up @@ -840,7 +840,7 @@ def _format_callback(self, obj, user, admin_site, perms_needed):
else:
# Don't display link to edit, because it either has no
# admin or is edited inline.
return '{}: {}'.format(capfirst(opts.verbose_name), force_str(obj))
return f'{capfirst(opts.verbose_name)}: {force_str(obj)}'

def _check_copy_perms(self, request, files_queryset, folders_queryset):
try:
Expand Down Expand Up @@ -1073,7 +1073,7 @@ def _get_available_name(self, destination, name):
count = itertools.count(1)
original = name
while destination.contains_folder(name):
name = "{}_{}".format(original, next(count))
name = f"{original}_{next(count)}"
return name

def _copy_folder(self, folder, destination, suffix, overwrite):
Expand Down
2 changes: 1 addition & 1 deletion filer/fields/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def render(self, name, value, attrs=None, renderer=None):
hidden_input = super(ForeignKeyRawIdWidget, self).render(name, value, attrs) # grandparent super
context = {
'hidden_input': hidden_input,
'lookup_url': '{}{}'.format(related_url, lookup_url),
'lookup_url': f'{related_url}{lookup_url}',
'change_url': change_url,
'object': obj,
'lookup_name': name,
Expand Down
2 changes: 1 addition & 1 deletion filer/fields/folder.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def render(self, name, value, attrs=None, renderer=None):
# API to determine the ID dynamically.
context = {
'hidden_input': hidden_input,
'lookup_url': '{}{}'.format(related_url, url),
'lookup_url': f'{related_url}{url}',
'lookup_name': name,
'span_id': css_id_description_txt,
'object': obj,
Expand Down
2 changes: 1 addition & 1 deletion filer/fields/multistorage_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def value_to_string(self, obj):
encoded_string = base64.b64encode(payload_file.read()).decode('utf-8')
return value, encoded_string
except OSError:
warnings.warn('The payload for "{}" is missing. No such file on disk: {}!'.format(obj.original_filename, self.storage.location))
warnings.warn(f'The payload for "{obj.original_filename}" is missing. No such file on disk: {self.storage.location}!')
return value

def to_python(self, value):
Expand Down
2 changes: 1 addition & 1 deletion filer/models/clipboardmodels.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def append_file(self, file_obj):
return True

def __str__(self):
return "Clipboard {} of {}".format(self.id, self.user)
return f"Clipboard {self.id} of {self.user}"


class ClipboardItem(models.Model):
Expand Down
6 changes: 3 additions & 3 deletions filer/models/filemodels.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,9 @@ class Meta:

def __str__(self):
if self.name in ('', None):
text = "{}".format(self.original_filename)
text = f"{self.original_filename}"
else:
text = "{}".format(self.name)
text = f"{self.name}"
return text

@classmethod
Expand Down Expand Up @@ -312,7 +312,7 @@ def label(self):
text = self.original_filename or 'unnamed file'
else:
text = self.name
text = "{}".format(text)
text = f"{text}"
return text

def __lt__(self, other):
Expand Down
2 changes: 1 addition & 1 deletion filer/models/thumbnailoptionmodels.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Meta:
verbose_name_plural = _("thumbnail options")

def __str__(self):
return '{} -- {} x {}'.format(self.name, self.width, self.height)
return f'{self.name} -- {self.width} x {self.height}'

@property
def as_dict(self):
Expand Down
5 changes: 4 additions & 1 deletion filer/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@
settings, 'FILER_FILE_MODELS',
(FILER_IMAGE_MODEL, 'filer.File'))

DEFAULT_FILE_STORAGE = getattr(settings, 'DEFAULT_FILE_STORAGE', 'django.core.files.storage.FileSystemStorage')
if hasattr(settings, "STORAGES") and 'default' in settings.STORAGES:
DEFAULT_FILE_STORAGE = settings.STORAGES['default'].get('BACKEND', 'django.core.files.storage.FileSystemStorage')
else:
DEFAULT_FILE_STORAGE = getattr(settings, 'DEFAULT_FILE_STORAGE', 'django.core.files.storage.FileSystemStorage')

MINIMAL_FILER_STORAGES = {
'public': {
Expand Down
2 changes: 1 addition & 1 deletion filer/templatetags/filer_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def filesize(bytes, format='auto1024'):
unit = '{}{}'.format(base == 1024 and unit.upper() or unit,
base == 1024 and 'iB' or 'B')

return '{} {}'.format(bytes, unit)
return f'{bytes} {unit}'

if bytes == 0:
return bytes
Expand Down
2 changes: 1 addition & 1 deletion tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def create_folder_structure(depth=2, sibling=2, parent=None):
depth_range.reverse()
for d in depth_range:
for s in range(1, sibling + 1):
name = "folder: %s -- %s" % (str(d), str(s))
name = "folder: {} -- {}".format(str(d), str(s))
folder = Folder(name=name, parent=parent)
folder.save()
create_folder_structure(depth=d - 1, sibling=sibling, parent=folder)
Expand Down
32 changes: 16 additions & 16 deletions tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ def test_filer_ajax_upload_file_error(self):
'admin:filer-ajax_upload',
kwargs={
'folder_id': folder.pk + 1}
) + '?filename={0}'.format(self.image_name)
) + f'?filename={self.image_name}'
response = self.client.post(
url,
data=file_obj.read(),
Expand Down Expand Up @@ -693,7 +693,7 @@ def test_filer_ajax_upload_without_permissions_error(self, extra_headers={}):
'admin:filer-ajax_upload',
kwargs={
'folder_id': folder.pk}
) + '?filename={0}'.format(self.image_name)
) + f'?filename={self.image_name}'
response = self.client.post(
url,
data=file_obj.read(),
Expand Down Expand Up @@ -759,7 +759,7 @@ def test_filer_ajax_upload_permissions_error(self, extra_headers={}):
'admin:filer-ajax_upload',
kwargs={
'folder_id': folder.pk}
) + '?filename={0}'.format(self.image_name)
) + f'?filename={self.image_name}'
response = self.client.post(
url,
data=file_obj.read(),
Expand Down Expand Up @@ -1103,10 +1103,10 @@ def _do_test_rename(self, url, new_name, file_obj=None, folder_obj=None):
'new_name' should be a plain string, no formatting supported.
"""
if file_obj is not None:
checkbox_name = 'file-{}'.format(file_obj.id)
checkbox_name = f'file-{file_obj.id}'
files = [file_obj]
elif folder_obj is not None:
checkbox_name = 'folder-{}'.format(folder_obj.id)
checkbox_name = f'folder-{folder_obj.id}'
# files inside this folder, non-recursive
files = File.objects.filter(folder=folder_obj)
else:
Expand Down Expand Up @@ -1322,9 +1322,9 @@ def test_with_permissions_disabled(self):
item_list = response.context['paginated_items'].object_list
# user sees all items: FOO, BAR, BAZ, SAMP
self.assertEqual(
set(folder.pk for folder in item_list),
set([self.foo_folder.pk, self.bar_folder.pk, self.baz_folder.pk,
self.spam_file.pk]))
{folder.pk for folder in item_list},
{self.foo_folder.pk, self.bar_folder.pk, self.baz_folder.pk, self.spam_file.pk}
)

def test_folder_ownership(self):
with SettingsOverride(filer_settings, FILER_ENABLE_PERMISSIONS=True):
Expand All @@ -1336,8 +1336,8 @@ def test_folder_ownership(self):
# he doesn't see BAR, BAZ and SPAM because he doesn't own them
# and no permission has been given
self.assertEqual(
set(folder.pk for folder in item_list),
set([self.foo_folder.pk]))
{folder.pk for folder in item_list},
{self.foo_folder.pk})

def test_with_permission_given_to_folder(self):
with SettingsOverride(filer_settings, FILER_ENABLE_PERMISSIONS=True):
Expand All @@ -1355,8 +1355,8 @@ def test_with_permission_given_to_folder(self):
item_list = response.context['paginated_items'].object_list
# user sees 2 folder : FOO, BAR
self.assertEqual(
set(folder.pk for folder in item_list),
set([self.foo_folder.pk, self.bar_folder.pk]))
{folder.pk for folder in item_list},
{self.foo_folder.pk, self.bar_folder.pk})

def test_with_permission_given_to_parent_folder(self):
with SettingsOverride(filer_settings, FILER_ENABLE_PERMISSIONS=True):
Expand All @@ -1373,9 +1373,9 @@ def test_with_permission_given_to_parent_folder(self):
item_list = response.context['paginated_items'].object_list
# user sees all items because he has permissions on the parent folder
self.assertEqual(
set(folder.pk for folder in item_list),
set([self.foo_folder.pk, self.bar_folder.pk, self.baz_folder.pk,
self.spam_file.pk]))
{folder.pk for folder in item_list},
{self.foo_folder.pk, self.bar_folder.pk, self.baz_folder.pk, self.spam_file.pk}
)

def test_search_against_owner(self):
url = reverse('admin:filer-directory_listing',
Expand Down Expand Up @@ -1416,7 +1416,7 @@ def test_search_special_characters(self):

# Create a file with a problematic filename
problematic_file = django.core.files.base.ContentFile('some data')
filename = u'christopher_eccleston'
filename = 'christopher_eccleston'
problematic_file.name = filename
self.spam_file = File.objects.create(
owner=self.staff_user, original_filename=filename,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_form_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ def test_widget_has_change_button(self):
content = widget.render("foo", file.id, {})

self.assertIn(
"/admin/filer/file/{}/change/?_edit_from_widget=1".format(file.id), content
f"/admin/filer/file/{file.id}/change/?_edit_from_widget=1", content
)
2 changes: 1 addition & 1 deletion tests/test_migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ def test_for_missing_migrations(self):
status_code = '0'

if status_code == '1':
self.fail('There are missing migrations:\n {}'.format(output.getvalue()))
self.fail(f'There are missing migrations:\n {output.getvalue()}')
6 changes: 3 additions & 3 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,19 @@ def test_create_icons(self):
self.assertEqual(len(icons), len(filer_settings.FILER_ADMIN_ICON_SIZES))
for size in filer_settings.FILER_ADMIN_ICON_SIZES:
self.assertEqual(os.path.basename(icons[size]),
file_basename + '__%sx%s_q85_crop_subsampling-2_upscale.jpg' % (size, size))
file_basename + '__{}x{}_q85_crop_subsampling-2_upscale.jpg'.format(size, size))

def test_access_icons_property(self):
"""Test IconsMixin that calls static on a non-existent file"""

class CustomObj(IconsMixin, object):
class CustomObj(IconsMixin):
_icon = 'custom'

custom_obj = CustomObj()
try:
icons = custom_obj.icons
except Exception as e:
self.fail("'.icons' access raised Exception {0} unexpectedly!".format(e))
self.fail(f"'.icons' access raised Exception {e} unexpectedly!")
self.assertEqual(len(icons), len(filer_settings.FILER_ADMIN_ICON_SIZES))

def test_file_upload_public_destination(self):
Expand Down
Loading