From 1dbd1c1779a765c743a896d315e2dce43f6382f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9DNyymix=E2=80=9D?= Date: Mon, 20 Jan 2025 21:21:09 +0200 Subject: [PATCH] Add redir model, remove children albums --- config/urls.py | 2 +- gallery/admin.py | 52 ++++++++++++++++++++++++------ gallery/migrations/0001_initial.py | 16 +++++++-- gallery/models/__init__.py | 1 + gallery/models/album.py | 10 ++---- gallery/models/location.py | 2 ++ gallery/models/redir.py | 14 ++++++++ gallery/urls.py | 2 +- gallery/views.py | 8 ++++- 9 files changed, 84 insertions(+), 23 deletions(-) create mode 100644 gallery/models/redir.py diff --git a/config/urls.py b/config/urls.py index e3e911e..daa6e4d 100644 --- a/config/urls.py +++ b/config/urls.py @@ -4,8 +4,8 @@ from django.contrib import admin from django.urls import include, path urlpatterns = [ - path('', include(('gallery.urls', 'gallery'), namespace='gallery')), path('admin/', admin.site.urls), + path('', include(('gallery.urls', 'gallery'), namespace='gallery')), ] if settings.DEBUG: diff --git a/gallery/admin.py b/gallery/admin.py index 8036d70..65c3b58 100644 --- a/gallery/admin.py +++ b/gallery/admin.py @@ -5,7 +5,7 @@ from imagekit.admin import AdminThumbnail from imagekit.cachefiles import ImageCacheFile from imagekit.processors import ResizeToFit -from gallery.models import Album, City, Location, Photo +from gallery.models import Album, City, Location, Photo, Redir class AdminThumbnailSpec(ImageSpec): @@ -20,6 +20,26 @@ def cached_admin_thumb(instance): return cached +class RedirAdmin(admin.ModelAdmin): + list_display = ('path', 'album', 'test_url') + search_fields = ('path',) + ordering = ('path',) + list_per_page = 10 + list_editable = ('album',) + + def formfield_for_foreignkey(self, db_field, request, **kwargs): + if db_field.name == "album": + kwargs["queryset"] = Album.objects.all().order_by('name') # Järjestä albumit aakkosjärjestykseen + return super().formfield_for_foreignkey(db_field, request, **kwargs) + + def test_url(self, obj): + return format_html( + 'http://nyymix.net/{}', + obj.path, obj.path + ) + test_url.short_description = "Test redirection" + + class CityAdmin(admin.ModelAdmin): list_display = ('name',) search_fields = ('name',) @@ -37,39 +57,53 @@ class LocationAdmin(admin.ModelAdmin): class AlbumAdmin(admin.ModelAdmin): prepopulated_fields = {'slug': ('name',)} - list_display = ('__str__', 'location', 'album_date', 'is_public', 'thumbnail', ) + list_display = ('__str__', 'name', 'location', 'album_date', 'is_public', 'thumbnail', ) search_fields = ('name',) ordering = ('-album_date',) - list_per_page = 30 - list_editable = ('is_public', 'location') + list_per_page = 20 + list_editable = ('name', 'is_public', 'location') + readonly_fields = ['cover_preview'] # Lisätään esikatselukuva readonly_fieldsiin + + def cover_preview(self, obj): + if obj.cover and obj.cover.photo: + return format_html( + '', + obj.cover.photo.url, + ) + return "No cover image available" + cover_preview.short_description = "Cover Preview" def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == "cover": if hasattr(request, 'resolver_match') and request.resolver_match.kwargs.get('object_id'): album_id = request.resolver_match.kwargs['object_id'] kwargs["queryset"] = Photo.objects.filter(album_id=album_id) + return super().formfield_for_foreignkey(db_field, request, **kwargs) - + def thumbnail(self, obj): if obj.cover and obj.cover.photo: return format_html( - '', + '', obj.cover.photo.url, ) return "-" thumbnail.short_description = "Thumbnail" - class PhotoAdmin(admin.ModelAdmin): - list_display = ('slug', 'album', 'admin_thumbnail',) + list_display = ('slug', 'album', 'is_favorite', 'admin_thumbnail',) list_display_links = ('slug',) - search_fields = ('slug',) + search_fields = ('slug', 'photo',) readonly_fields = ['slug', 'taken_at', 'height', 'width', 'exif', ] admin_thumbnail = AdminThumbnail(image_field=cached_admin_thumb) + list_filter = ('album',) + list_per_page = 30 + list_editable = ('is_favorite',) admin.site.register(City, CityAdmin) admin.site.register(Location, LocationAdmin) admin.site.register(Album, AlbumAdmin) admin.site.register(Photo, PhotoAdmin) +admin.site.register(Redir, RedirAdmin) diff --git a/gallery/migrations/0001_initial.py b/gallery/migrations/0001_initial.py index e8626ae..94c7531 100644 --- a/gallery/migrations/0001_initial.py +++ b/gallery/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.1.4 on 2025-01-18 07:39 +# Generated by Django 5.1.4 on 2025-01-20 19:09 import datetime import django.db.models.deletion @@ -33,7 +33,7 @@ class Migration(migrations.Migration): ], options={ 'verbose_name_plural': 'Locations', - 'unique_together': {('place', 'city')}, + 'unique_together': {('city', 'place')}, }, ), migrations.CreateModel( @@ -44,7 +44,6 @@ class Migration(migrations.Migration): ('slug', models.SlugField(max_length=150, unique=True, verbose_name='Slug')), ('album_date', models.DateField(default=datetime.datetime.now, verbose_name='Album Date')), ('is_public', models.BooleanField(default=False, verbose_name='Published')), - ('parent', models.ForeignKey(blank=True, limit_choices_to={'parent__isnull': True}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='gallery.album', verbose_name='Parent Album')), ('location', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='albums', to='gallery.location', verbose_name='Location')), ], options={ @@ -77,4 +76,15 @@ class Migration(migrations.Migration): name='cover', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='cover_to', to='gallery.photo', verbose_name='Album cover'), ), + migrations.CreateModel( + name='Redir', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('path', models.CharField(db_index=True, max_length=255, unique=True, verbose_name='Path')), + ('album', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pathurl', to='gallery.album', verbose_name='Album')), + ], + options={ + 'verbose_name_plural': 'Redirs', + }, + ), ] diff --git a/gallery/models/__init__.py b/gallery/models/__init__.py index 0721982..9b14cb2 100644 --- a/gallery/models/__init__.py +++ b/gallery/models/__init__.py @@ -1,3 +1,4 @@ from .album import * from .location import * from .photo import * +from .redir import * diff --git a/gallery/models/album.py b/gallery/models/album.py index 66a7935..bfc0e4b 100644 --- a/gallery/models/album.py +++ b/gallery/models/album.py @@ -12,7 +12,6 @@ from gallery.models.location import Location class Album(models.Model): name = models.CharField(max_length=150, unique=True, verbose_name="Album") slug = models.SlugField(max_length=150, unique=True, verbose_name="Slug") - parent = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True, limit_choices_to={'parent__isnull': True}, related_name='children', verbose_name="Parent Album") location = models.ForeignKey(Location, blank=True, null=True, on_delete=models.SET_NULL, related_name='albums', verbose_name="Location") album_date = models.DateField(default=datetime.now, verbose_name="Album Date") cover = models.ForeignKey("Photo", blank=True, null=True, on_delete=models.SET_NULL, related_name='cover_to', verbose_name="Album cover") @@ -21,12 +20,12 @@ class Album(models.Model): @property def photos_in_album(self): return self.photos.count() - + @property def photos_views(self): total_views = sum(self.photos.views()) return total_views - + @property def cover_url(self): if self.cover: @@ -35,11 +34,6 @@ class Album(models.Model): if random_cover: return random_cover.photo_md.url return static('img/placeholder.png') - - def clean(self): - super().clean() - if self.parent and self.parent == self: - raise ValidationError({'parent': "An album cannot be its own parent."}) def save(self, *args, **kwargs): if not self.slug: diff --git a/gallery/models/location.py b/gallery/models/location.py index 9790efe..7338d60 100644 --- a/gallery/models/location.py +++ b/gallery/models/location.py @@ -18,6 +18,8 @@ class Location(models.Model): class Meta: verbose_name_plural = "Locations" unique_together = ('place', "city") + ordering = ['city'] + def __str__(self): if self.place: diff --git a/gallery/models/redir.py b/gallery/models/redir.py new file mode 100644 index 0000000..3473b6a --- /dev/null +++ b/gallery/models/redir.py @@ -0,0 +1,14 @@ +from django.db import models + +from gallery.models import Album + + +class Redir(models.Model): + path = models.CharField(max_length=255, db_index=True, unique=True, verbose_name="Path") + album = models.ForeignKey(Album, on_delete=models.CASCADE, related_name='pathurl', verbose_name="Album") + + class Meta: + verbose_name_plural = "Redirs" + + def __str__(self): + return '{0} - {1}'.format(self.path, self.album.slug) diff --git a/gallery/urls.py b/gallery/urls.py index 1ca5714..884fe21 100644 --- a/gallery/urls.py +++ b/gallery/urls.py @@ -11,5 +11,5 @@ urlpatterns = [ path('albums///', views.PhotoDetail.as_view(), name='photo_url'), path('albums//', views.AlbumDetail.as_view(), name='album_url'), path('albums/', views.AlbumsList.as_view(), name='albums_url'), - + path('/', views.redirect_to_album, name='redirect_to_album'), ] diff --git a/gallery/views.py b/gallery/views.py index 2f64dbb..7298d39 100644 --- a/gallery/views.py +++ b/gallery/views.py @@ -2,7 +2,7 @@ from django.core.paginator import Paginator from django.shortcuts import get_object_or_404, redirect, render from django.views.generic import DetailView, ListView, TemplateView -from .models import Album, Photo +from .models import Album, Photo, Redir class Main(TemplateView): @@ -86,3 +86,9 @@ class PhotoDetail(DetailView): photo.save() return redirect('gallery:photo_url', album_slug=self.kwargs['album_slug'], photo_slug=self.kwargs['photo_slug']) + + + +def redirect_to_album(request, redir_path): + redir = get_object_or_404(Redir, path=redir_path) + return redirect('gallery:album_url', album_slug=redir.album.slug) \ No newline at end of file