refactor: split directory and image rendering into viewer.directory, viewer.image; add viewer.common for shared helpers
This commit is contained in:
163
viewer/directory.py
Normal file
163
viewer/directory.py
Normal file
@@ -0,0 +1,163 @@
|
||||
"""
|
||||
Directory-related rendering helpers for the gallery view.
|
||||
"""
|
||||
|
||||
# Standard library imports.
|
||||
from pathlib import Path
|
||||
|
||||
# Django imports.
|
||||
from django.http import HttpResponseNotFound
|
||||
from django.shortcuts import render
|
||||
from django.conf import settings
|
||||
|
||||
# Project imports.
|
||||
from .common import (
|
||||
normalize_sort,
|
||||
normalize_theme,
|
||||
build_query,
|
||||
gallery_url,
|
||||
sort_images,
|
||||
build_sort_options,
|
||||
build_breadcrumbs,
|
||||
get_first_image_thumbnail_url,
|
||||
is_image_file,
|
||||
make_thumbnail,
|
||||
)
|
||||
|
||||
|
||||
def do_recursive_search(start_path, query):
|
||||
"""
|
||||
Gets all images and sub-directories inside the start_path whose name matches the given query,
|
||||
and then joins the results recursively by iterating in each sub-directory.
|
||||
"""
|
||||
|
||||
try:
|
||||
entries = [entry for entry in start_path.iterdir() if not entry.is_symlink()]
|
||||
except OSError:
|
||||
return [], []
|
||||
|
||||
all_subdirs = sorted(
|
||||
[entry for entry in entries if entry.is_dir()],
|
||||
key=lambda item: (item.name.lower(), str(item).lower()),
|
||||
)
|
||||
|
||||
subdirs = [entry for entry in all_subdirs if query.lower() in entry.name.lower()]
|
||||
|
||||
images = sorted(
|
||||
[
|
||||
entry
|
||||
for entry in entries
|
||||
if entry.is_file()
|
||||
and is_image_file(entry)
|
||||
and query.lower() in entry.name.lower()
|
||||
],
|
||||
key=lambda item: (item.name.lower(), str(item).lower()),
|
||||
)
|
||||
|
||||
for subdir in all_subdirs:
|
||||
rec_subdirs, rec_images = do_recursive_search(subdir, query.lower())
|
||||
subdirs.extend(rec_subdirs)
|
||||
images.extend(rec_images)
|
||||
|
||||
return subdirs, images
|
||||
|
||||
|
||||
def render_directory(request, path_text, full_path):
|
||||
"""
|
||||
Renders the gallery view related to directories, be it the contents of an actual directory
|
||||
in the file system, or logical gallery directories like search result pages.
|
||||
"""
|
||||
|
||||
search_text = request.GET.get("search", "").strip()
|
||||
sort_key = normalize_sort(request.GET.get("sort", "abc"))
|
||||
theme = normalize_theme(request.GET.get("theme", "dark"))
|
||||
query_state = build_query(search_text, sort_key, theme)
|
||||
|
||||
try:
|
||||
current_entries = [
|
||||
entry for entry in full_path.iterdir() if not entry.is_symlink()
|
||||
]
|
||||
except OSError:
|
||||
return HttpResponseNotFound("Not found")
|
||||
|
||||
current_subdirs = sorted(
|
||||
[entry for entry in current_entries if entry.is_dir()],
|
||||
key=lambda item: (
|
||||
item.name.lower(),
|
||||
str(item.relative_to(settings.GALLERY_ROOT)).lower(),
|
||||
),
|
||||
)
|
||||
|
||||
if search_text == "":
|
||||
images = [
|
||||
entry
|
||||
for entry in current_entries
|
||||
if entry.is_file() and is_image_file(entry)
|
||||
]
|
||||
else:
|
||||
_, images = do_recursive_search(full_path, search_text)
|
||||
|
||||
images = sort_images(images, sort_key)
|
||||
|
||||
image_data = []
|
||||
for image in images:
|
||||
rel_path = image.relative_to(settings.GALLERY_ROOT)
|
||||
image_url = gallery_url(rel_path, False, query_state)
|
||||
|
||||
thumbnail = None
|
||||
try:
|
||||
# use shared make_thumbnail so tests can patch viewer.common.make_thumbnail
|
||||
make_thumbnail(image)
|
||||
thumb_path = settings.THUMBNAILS_ROOT.joinpath(rel_path)
|
||||
if thumb_path.exists():
|
||||
thumbnail = "/thumbs/" + str(rel_path).replace("\\", "/")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
image_data.append(
|
||||
{"path": image_url, "name": image.name, "thumbnail": thumbnail}
|
||||
)
|
||||
|
||||
subdir_data = []
|
||||
for subdir in current_subdirs:
|
||||
rel_path = subdir.relative_to(settings.GALLERY_ROOT)
|
||||
subdir_data.append(
|
||||
{
|
||||
"path": gallery_url(rel_path, True, query_state),
|
||||
"name": subdir.name,
|
||||
"thumbnail": get_first_image_thumbnail_url(subdir),
|
||||
}
|
||||
)
|
||||
|
||||
next_theme = "light" if theme == "dark" else "dark"
|
||||
theme_query = {"sort": sort_key, "theme": next_theme}
|
||||
|
||||
if search_text != "":
|
||||
theme_query["search"] = search_text
|
||||
|
||||
search_action_query = {"sort": sort_key, "theme": theme}
|
||||
|
||||
context = {
|
||||
"path": path_text,
|
||||
"search_text": search_text,
|
||||
"theme": theme,
|
||||
"sort_key": sort_key,
|
||||
"sort_label": "",
|
||||
"sort_options": build_sort_options(request, search_text, sort_key, theme),
|
||||
"breadcrumbs": build_breadcrumbs(path_text, query_state),
|
||||
"images": image_data,
|
||||
"subdirs": subdir_data,
|
||||
"theme_toggle_url": gallery_url(
|
||||
Path(path_text) if path_text != "" else None, True, theme_query
|
||||
),
|
||||
"search_action_url": gallery_url(
|
||||
Path(path_text) if path_text != "" else None, True, search_action_query
|
||||
),
|
||||
}
|
||||
|
||||
# sort_label depends on SORT_LABELS in common; import lazily to avoid circulars
|
||||
from .common import SORT_LABELS
|
||||
|
||||
context["sort_label"] = SORT_LABELS.get(sort_key, "")
|
||||
|
||||
return render(request, "gallery_view.html", context)
|
||||
Reference in New Issue
Block a user