Remove extended models

This commit is contained in:
Alexandre Iooss 2022-01-30 10:53:58 +01:00
parent 3bc8a2b649
commit 8beedb3626
14 changed files with 66 additions and 155 deletions

View file

@ -79,8 +79,7 @@ production néccessite **une installation de Debian Bullseye ou plus récent**.
``` ```
$ sudo apt install nginx git gettext uwsgi uwsgi-plugin-python3 python3-venv \ $ sudo apt install nginx git gettext uwsgi uwsgi-plugin-python3 python3-venv \
python3-certbot-nginx python3-django python3-django-crispy-forms \ python3-certbot-nginx python3-django python3-django-crispy-forms \
python3-django-taggit python3-pil python3-exifread python3-django-allauth \ python3-pil python3-exifread python3-django-allauth python3-docutils
python3-psycopg2 python3-docutils
``` ```
2. **Clonage du dépot dans `/var/www/photos/photo21`** 2. **Clonage du dépot dans `/var/www/photos/photo21`**

View file

@ -1,4 +1,5 @@
from django.contrib import admin from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from .models import Gallery, Photo, Tag from .models import Gallery, Photo, Tag
@ -15,14 +16,19 @@ class GalleryAdmin(admin.ModelAdmin):
class PhotoAdmin(admin.ModelAdmin): class PhotoAdmin(admin.ModelAdmin):
list_display = ('title', 'date_taken', 'date_added', list_display = ('title', 'date_taken', 'date_added',
'is_public', 'view_count', 'admin_thumbnail') 'is_public', 'view_count', 'admin_thumbnail', 'get_owner')
list_filter = ['date_added', 'is_public'] list_filter = ['date_added', 'is_public', 'owner']
search_fields = ['title', 'slug', 'caption'] search_fields = ['title', 'slug', 'caption']
list_per_page = 10 list_per_page = 10
prepopulated_fields = {'slug': ('title',)} prepopulated_fields = {'slug': ('title',)}
readonly_fields = ('date_taken',) readonly_fields = ('date_taken',)
model = Photo model = Photo
def get_owner(self, obj):
return obj.owner.username
get_owner.admin_order_field = 'owner'
get_owner.short_description = _('owner')
class TagAdmin(admin.ModelAdmin): class TagAdmin(admin.ModelAdmin):
list_display = ('name',) list_display = ('name',)
@ -30,4 +36,6 @@ class TagAdmin(admin.ModelAdmin):
model = Tag model = Tag
admin.site.register(Gallery, GalleryAdmin)
admin.site.register(Photo, PhotoAdmin)
admin.site.register(Tag, TagAdmin) admin.site.register(Tag, TagAdmin)

View file

@ -178,7 +178,7 @@ class Gallery(models.Model):
verbose_name_plural = _('galleries') verbose_name_plural = _('galleries')
def __str__(self): def __str__(self):
return self.title return f"{ self.title } ({self.date_start})"
def get_absolute_url(self): def get_absolute_url(self):
return reverse('photologue:pl-gallery', args=[self.slug]) return reverse('photologue:pl-gallery', args=[self.slug])

View file

@ -7,7 +7,7 @@ from .models import Gallery, Photo
class GalleryDateView(LoginRequiredMixin): class GalleryDateView(LoginRequiredMixin):
queryset = Gallery.objects.filter(is_public=True) queryset = Gallery.objects.filter(is_public=True)
date_field = 'extended__date_start' date_field = 'date_start'
uses_datetime_field = False # Fix related object access uses_datetime_field = False # Fix related object access
allow_empty = True allow_empty = True

View file

@ -1,47 +0,0 @@
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from photologue.admin import GalleryAdmin as GalleryAdminDefault
from photologue.admin import PhotoAdmin as PhotoAdminDefault
from photologue.models import Gallery, Photo
from .models import GalleryExtended, PhotoExtended
class GalleryExtendedInline(admin.StackedInline):
model = GalleryExtended
can_delete = False
class GalleryAdmin(GalleryAdminDefault):
"""
Define our new one-to-one model as an inline of Photologue's Gallery
model.
"""
inlines = [GalleryExtendedInline, ]
class PhotoExtendedInline(admin.StackedInline):
model = PhotoExtended
can_delete = True
class PhotoAdmin(PhotoAdminDefault):
"""
Define our new one-to-one model as an inline of Photologue's Photo
model.
"""
inlines = [PhotoExtendedInline, ]
list_display = ('title', 'date_taken', 'date_added',
'is_public', 'view_count', 'admin_thumbnail', 'get_owner')
list_filter = ['date_added', 'is_public', 'extended__owner']
def get_owner(self, obj):
if not hasattr(obj, 'extended'):
return "No owner"
return obj.extended.owner.username
get_owner.admin_order_field = 'owner'
get_owner.short_description = _('owner')
admin.site.register(Gallery, GalleryAdmin)
admin.site.register(Photo, PhotoAdmin)

View file

@ -5,19 +5,7 @@ from crispy_forms.layout import Div, Layout, Submit
from django import forms from django import forms
from django.utils.text import slugify from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from photologue.models import Gallery from photologue.models import Gallery, Tag
from taggit.models import Tag
from .models import GalleryExtended
class GalleryChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
"""Show gallery event date."""
if hasattr(obj, 'extended'):
return f"{ obj.title } ({obj.extended.date_start})"
else:
return obj.title
class UploadForm(forms.Form): class UploadForm(forms.Form):
@ -29,7 +17,7 @@ class UploadForm(forms.Form):
'class': 'mb-3', 'class': 'mb-3',
}), }),
) )
gallery = GalleryChoiceField( gallery = forms.ModelChoiceField(
Gallery.objects.all(), Gallery.objects.all(),
label=_('Gallery'), label=_('Gallery'),
required=False, required=False,
@ -100,12 +88,12 @@ class UploadForm(forms.Form):
if not gallery: if not gallery:
# Create new gallery # Create new gallery
title = self.cleaned_data.get('new_gallery_title') title = self.cleaned_data.get('new_gallery_title')
gallery = Gallery.objects.create(title=title, slug=slugify(title)) gallery = Gallery.objects.create(
ext = GalleryExtended.objects.create( title=title,
gallery=gallery, slug=slugify(title),
date_start=self.cleaned_data['new_gallery_date_start'], date_start=self.cleaned_data['new_gallery_date_start'],
date_end=self.cleaned_data['new_gallery_date_end'], date_end=self.cleaned_data['new_gallery_date_end'],
) )
for tag in self.cleaned_data['new_gallery_tags']: for tag in self.cleaned_data['new_gallery_tags']:
ext.tags.add(tag) gallery.tags.add(tag)
return gallery return gallery

View file

@ -16,7 +16,7 @@ class Command(BaseCommand):
media_dir = Path(settings.MEDIA_ROOT) media_dir = Path(settings.MEDIA_ROOT)
for gallery in Gallery.objects.all(): for gallery in Gallery.objects.all():
# Create gallery directory # Create gallery directory
gallery_year = str(gallery.extended.date_start.year) gallery_year = str(gallery.date_start.year)
gallery_dir = Path('photos') / gallery_year / gallery.slug gallery_dir = Path('photos') / gallery_year / gallery.slug
gallery_path = media_dir / gallery_dir gallery_path = media_dir / gallery_dir
if not gallery_path.exists(): if not gallery_path.exists():

View file

@ -0,0 +1,27 @@
# Generated by Django 3.2.11 on 2022-01-30 09:53
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('photologue_custom', '0004_photoextended_license'),
]
operations = [
migrations.RemoveField(
model_name='photoextended',
name='owner',
),
migrations.RemoveField(
model_name='photoextended',
name='photo',
),
migrations.DeleteModel(
name='GalleryExtended',
),
migrations.DeleteModel(
name='PhotoExtended',
),
]

View file

@ -1,64 +0,0 @@
from django.db import models
from django.conf import settings
from taggit.managers import TaggableManager
from photologue.models import Gallery, Photo
from django.utils.translation import gettext_lazy as _
class GalleryExtended(models.Model):
# Extend Photologue Gallery model.
gallery = models.OneToOneField(
Gallery,
related_name='extended',
on_delete=models.CASCADE,
)
# Add tags
tags = TaggableManager(blank=True)
# Add start and end dates fields to GalleryExtend
date_start = models.DateField(
blank=True,
null=True,
verbose_name=_("start date"),
)
date_end = models.DateField(
blank=True,
null=True,
verbose_name=_("end date"),
)
class Meta:
verbose_name = 'Extra fields'
verbose_name_plural = 'Extra fields'
def __str__(self):
return self.gallery.title
class PhotoExtended(models.Model):
# Extend Photologue Photo model.
photo = models.OneToOneField(
Photo,
related_name='extended',
on_delete=models.CASCADE,
)
# Add a owner field to PhotoExtended
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
verbose_name=_("owner"),
)
license = models.CharField(
max_length=255,
blank=True,
verbose_name=_("license"),
)
class Meta:
verbose_name = 'Extra fields'
verbose_name_plural = 'Extra fields'
def __str__(self):
return str(self.photo)

View file

@ -38,10 +38,10 @@ SPDX-License-Identifier: GPL-3.0-or-later
</a> </a>
{% endif %} {% endif %}
</h1> </h1>
{% if gallery.extended.date_start %}<p class="text-muted small">{{ gallery.extended.date_start }}{% if gallery.extended.date_end and gallery.extended.date_end != gallery.extended.date_start %} {% trans "to" %} {{ gallery.extended.date_end }}{% endif %}</p>{% endif %} {% if gallery.date_start %}<p class="text-muted small">{{ gallery.date_start }}{% if gallery.date_end and gallery.date_end != gallery.date_start %} {% trans "to" %} {{ gallery.date_end }}{% endif %}</p>{% endif %}
{% if gallery.extended.tags.all %} {% if gallery.tags.all %}
<p class="text-muted"> <p class="text-muted">
Tags : {% for tag in gallery.extended.tags.all %} Tags : {% for tag in gallery.tags.all %}
<a class="badge rounded-pill bg-dark text-decoration-none" href="{% url 'photologue:tag-detail' tag.slug %}">{{ tag }}</a> <a class="badge rounded-pill bg-dark text-decoration-none" href="{% url 'photologue:tag-detail' tag.slug %}">{{ tag }}</a>
{% endfor %} {% endfor %}
</p> </p>
@ -70,7 +70,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
<div class="card-body row" id="lightgallery"> <div class="card-body row" id="lightgallery">
{% for photo in photos %} {% for photo in photos %}
<a class="col-6 col-md-3 mb-2 text-center" href="{{ photo.get_absolute_url }}" data-src="{{ photo.get_display_url }}" data-download-url="{{ photo.image.url }}" data-slide-name="{{ photo.id }}"> <a class="col-6 col-md-3 mb-2 text-center" href="{{ photo.get_absolute_url }}" data-src="{{ photo.get_display_url }}" data-download-url="{{ photo.image.url }}" data-slide-name="{{ photo.id }}">
<img src="{{ photo.get_thumbnail_url }}" loading="lazy" class="img-thumbnail p-0" alt="{{ photo.title }}{% if photo.date_taken %} - {{ photo.date_taken|date }} {{ photo.date_taken|time }}{% endif %} - {{ photo.extended.owner.get_full_name }}{% if photo.extended.license %} - {{ photo.extended.license }}{% endif %}"> <img src="{{ photo.get_thumbnail_url }}" loading="lazy" class="img-thumbnail p-0" alt="{{ photo.title }}{% if photo.date_taken %} - {{ photo.date_taken|date }} {{ photo.date_taken|time }}{% endif %} - {{ photo.owner.get_full_name }}{% if photo.license %} - {{ photo.license }}{% endif %}">
</a> </a>
{% endfor %} {% endfor %}
</div> </div>

View file

@ -6,7 +6,7 @@
{% endfor %} {% endfor %}
<div class="card-body"> <div class="card-body">
<h5 class="card-title">{{ gallery.title }}</h5> <h5 class="card-title">{{ gallery.title }}</h5>
{% if gallery.extended.date_start %}<p class="card-text text-muted small mb-0">{{ gallery.extended.date_start }}{% if gallery.extended.date_end and gallery.extended.date_end != gallery.extended.date_start %} - {{ gallery.extended.date_end }}{% endif %}</p>{% endif %} {% if gallery.date_start %}<p class="card-text text-muted small mb-0">{{ gallery.date_start }}{% if gallery.date_end and gallery.date_end != gallery.date_start %} - {{ gallery.date_end }}{% endif %}</p>{% endif %}
<a href="{{ gallery.get_absolute_url }}" class="stretched-link"></a> <a href="{{ gallery.get_absolute_url }}" class="stretched-link"></a>
</div> </div>
</div> </div>

View file

@ -16,12 +16,10 @@ from django.urls import reverse_lazy
from django.utils.text import slugify from django.utils.text import slugify
from django.views.generic.detail import DetailView from django.views.generic.detail import DetailView
from django.views.generic.edit import FormView from django.views.generic.edit import FormView
from photologue.models import Gallery, Photo from photologue.models import Gallery, Photo, Tag
from PIL import Image from PIL import Image
from taggit.models import Tag
from .forms import UploadForm from .forms import UploadForm
from .models import PhotoExtended
class TagDetail(LoginRequiredMixin, DetailView): class TagDetail(LoginRequiredMixin, DetailView):
@ -34,8 +32,8 @@ class TagDetail(LoginRequiredMixin, DetailView):
current_tag = self.get_object().slug current_tag = self.get_object().slug
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context['galleries'] = Gallery.objects.filter(is_public=True) \ context['galleries'] = Gallery.objects.filter(is_public=True) \
.filter(extended__tags__slug=current_tag) \ .filter(tags__slug=current_tag) \
.order_by('-extended__date_start') .order_by('-date_start')
return context return context
@ -48,18 +46,18 @@ class CustomGalleryDetailView(LoginRequiredMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
# Query with extended and owner to reduce database lag # Query with owner to reduce database lag
context['photos'] = self.object.public().select_related('extended__owner') context['photos'] = self.object.public().select_related('owner')
# List owners # List owners
context['owners'] = [] context['owners'] = []
for photo in context['photos']: for photo in context['photos']:
if hasattr(photo, 'extended') and photo.extended.owner not in context['owners']: if photo.owner not in context['owners']:
context['owners'].append(photo.extended.owner) context['owners'].append(photo.owner)
# Filter on owner # Filter on owner
if 'owner' in self.kwargs: if 'owner' in self.kwargs:
context['photos'] = context['photos'].filter(extended__owner__id=self.kwargs['owner']) context['photos'] = context['photos'].filter(owner__id=self.kwargs['owner'])
return context return context
@ -100,7 +98,7 @@ class GalleryUpload(PermissionRequiredMixin, FormView):
# We take files from the request to support multiple upload # We take files from the request to support multiple upload
files = self.request.FILES.getlist('file_field') files = self.request.FILES.getlist('file_field')
gallery = form.get_or_create_gallery() gallery = form.get_or_create_gallery()
gallery_year = Path(str(gallery.extended.date_start.year)) gallery_year = Path(str(gallery.date_start.year))
gallery_dir = gallery_year / gallery.slug gallery_dir = gallery_year / gallery.slug
failed_upload = 0 failed_upload = 0
for photo_file in files: for photo_file in files:
@ -116,12 +114,15 @@ class GalleryUpload(PermissionRequiredMixin, FormView):
title = f"{gallery.title} - {photo_file.name}" title = f"{gallery.title} - {photo_file.name}"
try: try:
photo = Photo(title=title, slug=slugify(title)) photo = Photo(
title=title,
slug=slugify(title),
owner=self.request.user,
)
photo_name = str(gallery_dir / photo_file.name) photo_name = str(gallery_dir / photo_file.name)
photo.image.save(photo_name, photo_file) photo.image.save(photo_name, photo_file)
photo.save() photo.save()
photo.galleries.set([gallery]) photo.galleries.set([gallery])
PhotoExtended.objects.create(photo=photo, owner=self.request.user)
except IntegrityError: except IntegrityError:
messages.error(self.request, f"{photo_file.name} was not uploaded. Maybe the photo was already uploaded.") messages.error(self.request, f"{photo_file.name} was not uploaded. Maybe the photo was already uploaded.")
failed_upload += 1 failed_upload += 1

View file

@ -1,6 +1,5 @@
django-allauth>=0.44 django-allauth>=0.44
django-crispy-forms~=1.7 django-crispy-forms~=1.7
django-taggit>=1.5.0
Django>=2.2.20 Django>=2.2.20
ExifRead>=2.1.2 ExifRead>=2.1.2
git+https://gitlab.crans.org/bde/allauth-note-kfet.git git+https://gitlab.crans.org/bde/allauth-note-kfet.git