Remove extended models
This commit is contained in:
parent
3bc8a2b649
commit
8beedb3626
14 changed files with 66 additions and 155 deletions
|
|
@ -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`**
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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])
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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():
|
||||||
|
|
|
||||||
27
photologue_custom/migrations/0005_auto_20220130_0953.py
Normal file
27
photologue_custom/migrations/0005_auto_20220130_0953.py
Normal 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',
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue