Added model for special galleries.

This commit is contained in:
Miguel Astor
2026-03-24 15:06:48 -04:00
parent 77d83c58d1
commit 5a6632491a
5 changed files with 122 additions and 3 deletions

View File

@@ -8,13 +8,16 @@ import datetime
# Django imports.
from django.http import HttpResponseNotFound
from django.shortcuts import render
from django.shortcuts import render, redirect
from django.conf import settings
from django.utils import timezone
# Third-party
from PIL import Image
# Project imports.
from .models import Image as Im
from .common import (
normalize_sort,
normalize_theme,
@@ -34,6 +37,20 @@ def render_image(request, path_text, full_path):
Renders the view corresponding to an image file.
"""
try:
img = Im.objects.get(path=full_path, user=request.user)
if request.method == 'POST':
img.favorite = not img.favorite
except Im.DoesNotExist:
img = Im(path=full_path, user=request.user)
finally:
img.last_visited = timezone.now()
img.visits = img.visits + 1
img.save()
# Preserve query state (sort, search, theme) similar to gallery view
search_text = request.GET.get("search", "").strip()
sort_key = normalize_sort(request.GET.get("sort", "abc"))
@@ -177,6 +194,9 @@ def render_image(request, path_text, full_path):
"filesize": human_size(filesize),
"created": fmt_ts(created_ts),
"modified": fmt_ts(modified_ts),
"visits": img.visits,
"visited": fmt_ts(img.last_visited.timestamp()),
"favorite": img.favorite
},
"breadcrumbs": breadcrumbs,
"theme": theme,
@@ -186,6 +206,7 @@ def render_image(request, path_text, full_path):
"theme_toggle_url": gallery_url(
Path(dir_path_text) if dir_path_text != "" else None, True, theme_query
),
"path": path_text,
}
from .common import SORT_LABELS

View File

@@ -0,0 +1,52 @@
# Generated by Django 6.0.3 on 2026-03-24 18:56
import django.db.models.deletion
import django.utils.timezone
import pathlib
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="Image",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"path",
models.FilePathField(
path=pathlib.PurePosixPath("/home/miky/Imágenes")
),
),
("favorite", models.BooleanField(default=False)),
(
"last_visited",
models.DateTimeField(default=django.utils.timezone.now),
),
("visits", models.IntegerField(default=0)),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
],
),
]

27
viewer/models.py Normal file
View File

@@ -0,0 +1,27 @@
from django.utils import timezone
from django.conf import settings
from django.db.models import (
Model,
BooleanField,
DateTimeField,
IntegerField,
FilePathField,
ForeignKey,
CASCADE
)
class Image(Model):
"""
User relations to a specific image file by path.
"""
user = ForeignKey(settings.AUTH_USER_MODEL, blank=False, null=False, on_delete=CASCADE)
path = FilePathField(path=settings.GALLERY_ROOT, blank=False, null=False)
favorite = BooleanField(blank=False, null=False, default=False)
last_visited = DateTimeField(blank=False, null=False, default=timezone.now)
visits = IntegerField(blank=False, null=False, default=0)
class meta:
ordering = ["pk"]
get_latest_by = "-last_visited"

View File

@@ -240,7 +240,7 @@ body {
}
.info-menu {
min-width: 220px;
min-width: 275px;
border-radius: 8px;
}

View File

@@ -117,12 +117,23 @@
{% endfor %}
</div>
<form method="post" action="{% url 'gallery_view_path' path=path %}">
{% csrf_token %}
<button class="btn btn-sm btn-plain" type="submit" title="Favorite" aria-label="Fav image" name="favorite">
{% if image_meta.favorite %}
<i class="fa-solid fa-star"></i>
{% else %}
<i class="fa-regular fa-star"></i>
{% endif %}
</button>
</form>
<div class="dropdown ms-auto">
<button class="btn btn-sm btn-plain" type="button" data-bs-toggle="dropdown" aria-expanded="false" title="Info" aria-label="Image info">
<i class="fa-solid fa-circle-info"></i>
</button>
<div class="dropdown-menu dropdown-menu-end info-menu p-2">
<div style="max-height:220px; overflow:auto;">
<div style="max-height:300px; overflow:auto;">
<div class="small text-muted">{{ image_meta.filename|truncatechars:40 }}</div>
{% if image_meta.width and image_meta.height %}
<div>{{ image_meta.width }} x {{ image_meta.height }} px</div>
@@ -138,6 +149,14 @@
<div class="small text-muted">Modification date</div>
<div>{{ image_meta.modified }}</div>
{% endif %}
{% if image_meta.visits %}
<div class="small text-muted">Visits:</div>
<div>{{ image_meta.visits }}</div>
{% endif %}
{% if image_meta.visited %}
<div class="small text-muted">Last visit:</div>
<div>{{ image_meta.visited }}</div>
{% endif %}
</div>
</div>
</div>