Skip to content

Commit 6961cbc

Browse files
committed
fix: enhance thumbnail handling for public and private files
1 parent c610365 commit 6961cbc

File tree

4 files changed

+102
-6
lines changed

4 files changed

+102
-6
lines changed

filer/admin/folderadmin.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,30 @@ def directory_listing(self, request, folder_id=None, viewtype=None):
375375
.order_by("-modified")
376376
)
377377
file_qs = file_qs.annotate(
378-
thumbnail_name=Subquery(thumbnail_qs.filter(name__contains=f"__{size}_").values_list("name")[:1]),
379-
thumbnailx2_name=Subquery(thumbnail_qs.filter(name__contains=f"__{size_x2}_").values_list("name")[:1])
378+
# For private files (Filer pattern)
379+
thumbnail_name_filer=Subquery(
380+
thumbnail_qs.filter(name__contains=f"__{size}_").values_list("name")[:1]
381+
),
382+
thumbnailx2_name_filer=Subquery(
383+
thumbnail_qs.filter(name__contains=f"__{size_x2}_").values_list("name")[
384+
:1
385+
]
386+
),
387+
# For public files (easy_thumbnails pattern)
388+
thumbnail_name_easy=Subquery(
389+
thumbnail_qs.filter(name__contains=f".{size}_q85_crop").values_list(
390+
"name"
391+
)[:1]
392+
),
393+
thumbnailx2_name_easy=Subquery(
394+
thumbnail_qs.filter(name__contains=f".{size_x2}_q85_crop").values_list(
395+
"name"
396+
)[:1]
397+
),
398+
thumbnail_name=Coalesce("thumbnail_name_filer", "thumbnail_name_easy"),
399+
thumbnailx2_name=Coalesce(
400+
"thumbnailx2_name_filer", "thumbnailx2_name_easy"
401+
),
380402
).select_related("owner")
381403

382404
try:

filer/utils/filer_easy_thumbnails.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,19 @@ def get_thumbnail_name(self, thumbnail_options, transparent=False):
2727
"""
2828
A version of ``Thumbnailer.get_thumbnail_name`` that produces a
2929
reproducible thumbnail name that can be converted back to the original
30-
filename.
30+
filename. For public files, it uses easy_thumbnails default naming.
3131
"""
32+
is_public = False
33+
if hasattr(self, "thumbnail_storage"):
34+
is_public = "PrivateFileSystemStorage" not in str(
35+
self.thumbnail_storage.__class__
36+
)
37+
38+
if is_public:
39+
return super(ThumbnailerNameMixin, self).get_thumbnail_name(
40+
thumbnail_options, transparent
41+
)
42+
3243
path, source_filename = os.path.split(self.name)
3344
source_extension = os.path.splitext(source_filename)[1][1:].lower()
3445
preserve_extensions = self.thumbnail_preserve_extensions

tests/test_models.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,14 @@ def tearDown(self):
3535
for f in File.objects.all():
3636
f.delete()
3737

38-
def create_filer_image(self, owner=None):
38+
def create_filer_image(self, owner=None, is_public=True):
3939
if owner is None:
4040
owner = self.superuser
4141
file_obj = DjangoFile(open(self.filename, 'rb'), name=self.image_name)
4242
image = Image.objects.create(owner=owner,
4343
original_filename=self.image_name,
44-
file=file_obj)
44+
file=file_obj,
45+
is_public=is_public)
4546
return image
4647

4748
def test_create_folder_structure(self):
@@ -80,7 +81,7 @@ def test_create_clipboard_item(self):
8081
self.assertEqual(Clipboard.objects.count(), 1)
8182

8283
def test_create_icons(self):
83-
image = self.create_filer_image()
84+
image = self.create_filer_image(is_public=False)
8485
image.save()
8586
icons = image.icons
8687
file_basename = os.path.basename(image.file.path)

tests/test_thumbnails.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import os
2+
3+
from django.conf import settings
4+
from django.core.files import File as DjangoFile
5+
from django.test import TestCase, override_settings
6+
7+
from filer.models.filemodels import File
8+
from filer.settings import FILER_IMAGE_MODEL
9+
from filer.utils.loader import load_model
10+
from tests.helpers import create_image, create_superuser
11+
12+
Image = load_model(FILER_IMAGE_MODEL)
13+
14+
15+
def custom_namer(thumbnailer, **kwargs):
16+
path, filename = os.path.split(thumbnailer.name)
17+
return os.path.join(path, f"custom_prefix_{filename}")
18+
19+
20+
class ThumbnailNameTests(TestCase):
21+
def setUp(self):
22+
self.superuser = create_superuser()
23+
self.img = create_image()
24+
self.image_name = "test_file.jpg"
25+
self.filename = os.path.join(settings.FILE_UPLOAD_TEMP_DIR, self.image_name)
26+
self.img.save(self.filename, "JPEG")
27+
28+
def tearDown(self):
29+
os.remove(self.filename)
30+
for f in File.objects.all():
31+
f.delete()
32+
33+
def create_filer_image(self, is_public=True):
34+
with open(self.filename, "rb") as f:
35+
file_obj = DjangoFile(f)
36+
image = Image.objects.create(
37+
owner=self.superuser,
38+
original_filename=self.image_name,
39+
file=file_obj,
40+
is_public=is_public,
41+
)
42+
return image
43+
44+
def test_thumbnailer_class_for_public_files(self):
45+
image = self.create_filer_image(is_public=True)
46+
thumbnailer = image.easy_thumbnails_thumbnailer
47+
name = thumbnailer.get_thumbnail_name({"size": (100, 100)})
48+
self.assertNotIn("__", name)
49+
50+
def test_thumbnailer_class_for_private_files(self):
51+
image = self.create_filer_image(is_public=False)
52+
thumbnailer = image.easy_thumbnails_thumbnailer
53+
name = thumbnailer.get_thumbnail_name({"size": (100, 100)})
54+
self.assertIn("__", name)
55+
56+
@override_settings(THUMBNAIL_NAMER="tests.test_thumbnails.custom_namer")
57+
def test_thumbnail_custom_namer(self):
58+
image = self.create_filer_image(is_public=True)
59+
thumbnailer = image.easy_thumbnails_thumbnailer
60+
name = thumbnailer.get_thumbnail_name({"size": (100, 100)})
61+
filename = os.path.basename(name)
62+
self.assertTrue(filename.startswith("custom_prefix_"))

0 commit comments

Comments
 (0)