143 lines
4.4 KiB
Python
143 lines
4.4 KiB
Python
"""Top-level views module.
|
|
|
|
After refactor this file only keeps the minimal public view entry points and imports
|
|
helpers from the new `directory` and `image` modules. Also provides the
|
|
`toggle_settings` view used by template buttons to persist theme/sort.
|
|
"""
|
|
|
|
# Django imports.
|
|
from urllib.parse import urlparse
|
|
from django.http import HttpResponseNotFound
|
|
from django.conf import settings
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.shortcuts import redirect
|
|
from django.core.exceptions import MultipleObjectsReturned
|
|
|
|
# Local helpers split into modules
|
|
from .directory import render_directory
|
|
from .image import render_image
|
|
|
|
from .models import UserSettings
|
|
|
|
|
|
SPECIALS = ['favorites', 'most-visited', 'recent']
|
|
|
|
|
|
@login_required
|
|
def index(request):
|
|
return redirect("gallery_view_root")
|
|
|
|
|
|
@login_required
|
|
def gallery_view(request, path=None):
|
|
"""
|
|
Shows a list of subdirectories and image files inside the given path.
|
|
The path should be inside the GALLERY_ROOT path, otherwise a 404 error will be thrown.
|
|
"""
|
|
|
|
root = settings.GALLERY_ROOT.resolve()
|
|
|
|
try:
|
|
candidate = root.joinpath(path).resolve() if path is not None else root
|
|
candidate.relative_to(root)
|
|
except Exception:
|
|
return HttpResponseNotFound("Not found")
|
|
|
|
if not candidate.exists():
|
|
return HttpResponseNotFound("Not found")
|
|
|
|
path_text = path if path is not None else ""
|
|
|
|
if candidate.is_dir():
|
|
return render_directory(request, path_text, candidate)
|
|
|
|
return render_image(request, path_text, candidate)
|
|
|
|
|
|
@login_required
|
|
def special_gallery_view(request, gallery, path=None):
|
|
"""
|
|
Shows a list of subdirectories and image files inside the given special gallery.
|
|
Available special galleries are: (1) favorites; (2) most visited; (3) recently visited.
|
|
"""
|
|
|
|
root = settings.GALLERY_ROOT.resolve()
|
|
|
|
if gallery not in SPECIALS:
|
|
return HttpResponseNotFound("Not found")
|
|
|
|
try:
|
|
candidate = root.joinpath(path).resolve() if path is not None else root
|
|
candidate.relative_to(root)
|
|
except Exception:
|
|
return HttpResponseNotFound("Not found")
|
|
|
|
path_text = path if path is not None else ""
|
|
|
|
if path is not None:
|
|
# Special galleries only have a logical root directory.
|
|
# When there is a valid sub-directory path inside the gallery root
|
|
# in the request then redirect to the base special gallery.
|
|
if candidate.is_dir():
|
|
return redirect('special_gallery_view_path', gallery, None, permanent=True)
|
|
|
|
else:
|
|
# When there is no path to render, then go to the corresponding special gallery root.
|
|
return render_directory(request, path_text, candidate, gallery)
|
|
|
|
# Fail if the requested image doesn' exist.
|
|
if not candidate.exists():
|
|
return HttpResponseNotFound("Not found")
|
|
|
|
# Images are rendered normally, with a control to ensure the back, next and previous buttons
|
|
# use the special gallery.
|
|
return render_image(request, path_text, candidate, gallery)
|
|
|
|
|
|
@login_required
|
|
def toggle_settings(request):
|
|
"""Persist theme and/or sort for the current user and redirect back.
|
|
|
|
Expected query params:
|
|
- next: the URL to redirect back to (optional)
|
|
- theme: optional, 'light' or 'dark'
|
|
- sort: optional, one of allowed sort keys
|
|
|
|
The view will obtain or create the UserSettings row for the user and set
|
|
any provided values. If multiple UserSettings rows exist (shouldn't
|
|
normally happen) the first is used.
|
|
"""
|
|
|
|
next_url = request.GET.get("next") or "/gallery/"
|
|
|
|
# Only allow in-site redirects for safety
|
|
parsed = urlparse(next_url)
|
|
if parsed.netloc and parsed.netloc != "":
|
|
next_url = "/gallery/"
|
|
|
|
user = getattr(request, "user", None)
|
|
if not user or not getattr(user, "is_authenticated", False):
|
|
return redirect(next_url)
|
|
|
|
# Obtain or create the settings row
|
|
try:
|
|
settings_obj = UserSettings.objects.get(user=user)
|
|
except UserSettings.DoesNotExist:
|
|
settings_obj = UserSettings(user=user)
|
|
except MultipleObjectsReturned:
|
|
settings_obj = UserSettings.objects.filter(user=user).first()
|
|
|
|
# Apply provided values
|
|
theme = request.GET.get("theme")
|
|
sort = request.GET.get("sort")
|
|
|
|
if theme in ("light", "dark"):
|
|
settings_obj.theme = theme
|
|
|
|
if sort:
|
|
settings_obj.sort = sort
|
|
|
|
settings_obj.save()
|
|
|
|
return redirect(next_url)
|