From 6ea1a7c77fc3540e85bc2fc3fc303eab2a54237a Mon Sep 17 00:00:00 2001 From: Alexandre Iooss <erdnaxe@crans.org> Date: Sun, 30 Jan 2022 10:19:08 +0100 Subject: [PATCH 1/9] Override logout template --- photo21/templates/account/logout.html | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 photo21/templates/account/logout.html diff --git a/photo21/templates/account/logout.html b/photo21/templates/account/logout.html new file mode 100644 index 0000000..7db6ac3 --- /dev/null +++ b/photo21/templates/account/logout.html @@ -0,0 +1,24 @@ +{% extends "account/base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-2.0-or-later +{% endcomment %} +{% load i18n %} +{% block head_title %}{% trans "Sign Out" %}{% endblock %} + +{% block content %} +<div class="card mx-auto"> + <h3 class="card-header text-center"> + {% trans "Sign Out" %} + </h3> + <div class="card-body"> + <p>{% trans 'Are you sure you want to sign out?' %}</p> + <form method="post" action="{% url 'account_logout' %}"> + {% csrf_token %} + {% if redirect_field_value %} + <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}"/> + {% endif %} + <button type="submit" class="btn btn-primary">{% trans 'Sign Out' %}</button> + </form> + </div> +</div> +{% endblock %} -- GitLab From 27b1590a10f9af23b551278652f8c48975299848 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss <erdnaxe@crans.org> Date: Sun, 30 Jan 2022 10:20:32 +0100 Subject: [PATCH 2/9] Add extended fields to the Photo and Gallery --- photologue/admin.py | 13 ++- photologue/migrations/0014_merge_related.py | 96 +++++++++++++++++++++ photologue/models.py | 47 ++++++++++ 3 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 photologue/migrations/0014_merge_related.py diff --git a/photologue/admin.py b/photologue/admin.py index 0c04abf..ff797fb 100644 --- a/photologue/admin.py +++ b/photologue/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from .models import Gallery, Photo +from .models import Gallery, Photo, Tag class GalleryAdmin(admin.ModelAdmin): @@ -9,7 +9,7 @@ class GalleryAdmin(admin.ModelAdmin): date_hierarchy = 'date_added' prepopulated_fields = {'slug': ('title',)} model = Gallery - autocomplete_fields = ['photos', ] + autocomplete_fields = ['photos', 'tags'] search_fields = ['title', ] @@ -22,3 +22,12 @@ class PhotoAdmin(admin.ModelAdmin): prepopulated_fields = {'slug': ('title',)} readonly_fields = ('date_taken',) model = Photo + + +class TagAdmin(admin.ModelAdmin): + list_display = ('name',) + search_fields = ('name',) + model = Tag + + +admin.site.register(Tag, TagAdmin) diff --git a/photologue/migrations/0014_merge_related.py b/photologue/migrations/0014_merge_related.py new file mode 100644 index 0000000..2608233 --- /dev/null +++ b/photologue/migrations/0014_merge_related.py @@ -0,0 +1,96 @@ +# Generated by Django 3.2.11 on 2022-01-30 08:32 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import taggit.managers +from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType +from django.template.defaultfilters import slugify + +numens = User.objects.get(username="Numens").id + +def migrate_related(apps, schema_editor): + Gallery = apps.get_model('photologue', 'Gallery') + Tag = apps.get_model('photologue', 'Tag') + TaggedItems = apps.get_model('taggit', 'TaggedItem') + ct_ext = ContentType.objects.get(app_label="photologue_custom", model="galleryextended") + for gallery in Gallery.objects.all(): + tagged_items = TaggedItems.objects.filter( + content_type_id=ct_ext.id, + object_id=gallery.extended.id + ) + tags = [tag.tag for tag in tagged_items.all()] + gallery.date_start = gallery.extended.date_start + gallery.date_end = gallery.extended.date_end + gallery.save() + for tag in tags: + try: + new_tag, created = Tag.objects.get_or_create( + name=tag.name.capitalize(), + slug=slugify(tag.name), + ) + if new_tag not in gallery.tags.all(): + gallery.tags.add(new_tag) + new_tag.save() + gallery.save() + except Exception: + continue + + Photo = apps.get_model('photologue', 'Photo') + for photo in Photo.objects.all(): + photo.owner = photo.extended.owner + photo.license = photo.extended.license + photo.save() + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('photologue', '0013_alter_gallery_photos'), + ] + + operations = [ + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=250, unique=True, verbose_name='name')), + ('slug', models.SlugField(help_text='A "slug" is a unique URL-friendly title for an object.', max_length=250, unique=True, verbose_name='slug')), + ], + options={ + 'verbose_name': 'tag', + 'verbose_name_plural': 'tags', + 'ordering': ['name'], + }, + ), + migrations.AddField( + model_name='gallery', + name='date_end', + field=models.DateField(blank=True, null=True, verbose_name='end date'), + ), + migrations.AddField( + model_name='gallery', + name='date_start', + field=models.DateField(default=django.utils.timezone.now, verbose_name='start date'), + ), + migrations.AddField( + model_name='photo', + name='license', + field=models.CharField(blank=True, max_length=255, verbose_name='license'), + ), + migrations.AddField( + model_name='photo', + name='owner', + field=models.ForeignKey(default=numens, on_delete=django.db.models.deletion.CASCADE, to='auth.user', verbose_name='owner'), + preserve_default=False, + ), + migrations.AddField( + model_name='gallery', + name='tags', + field=models.ManyToManyField(blank=True, related_name='galleries', to='photologue.Tag', verbose_name='tags'), + ), + migrations.RunPython(migrate_related), + ] diff --git a/photologue/models.py b/photologue/models.py index f38fbc5..059ac44 100644 --- a/photologue/models.py +++ b/photologue/models.py @@ -145,8 +145,23 @@ class Gallery(models.Model): unique=True, max_length=250, help_text=_('A "slug" is a unique URL-friendly title for an object.')) + date_start = models.DateField( + default=now, + verbose_name=_("start date"), + ) + date_end = models.DateField( + blank=True, + null=True, + verbose_name=_("end date"), + ) description = models.TextField(_('description'), blank=True) + tags = models.ManyToManyField( + 'photologue.Tag', + related_name='galleries', + verbose_name=_('tags'), + blank=True, + ) is_public = models.BooleanField(_('is public'), default=True, help_text=_('Public galleries will be displayed ' @@ -478,6 +493,16 @@ class Photo(ImageModel): blank=True) date_added = models.DateTimeField(_('date added'), default=now) + 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"), + ) is_public = models.BooleanField(_('is public'), default=True, help_text=_('Public photographs will be displayed in the default views.')) @@ -657,3 +682,25 @@ def init_size_method_map(): {'base_name': '_get_size_url', 'size': size} size_method_map['get_%s_filename' % size] = \ {'base_name': '_get_size_filename', 'size': size} + + +class Tag(models.Model): + name = models.CharField( + max_length=250, + unique=True, + verbose_name=_('name'), + ) + slug = models.SlugField( + unique=True, + max_length=250, + verbose_name=_('slug'), + help_text=_('A "slug" is a unique URL-friendly title for an object.'), + ) + + class Meta: + ordering = ['name'] + verbose_name = _('tag') + verbose_name_plural = _('tags') + + def __str__(self): + return self.name -- GitLab From 2a0f41deacf01aced64e7dacd4692b9bce8e77ce Mon Sep 17 00:00:00 2001 From: Alexandre Iooss <erdnaxe@crans.org> Date: Sun, 30 Jan 2022 10:21:05 +0100 Subject: [PATCH 3/9] Move urls.py in photologue --- photo21/urls.py | 2 +- {photologue_custom => photologue}/urls.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) rename {photologue_custom => photologue}/urls.py (73%) diff --git a/photo21/urls.py b/photo21/urls.py index 530068a..0538e1c 100644 --- a/photo21/urls.py +++ b/photo21/urls.py @@ -22,7 +22,7 @@ from .views import IndexView, MediaAccess urlpatterns = [ path('', IndexView.as_view(), name='index'), - path('', include('photologue_custom.urls', namespace='photologue')), + path('', include('photologue.urls', namespace='photologue')), path('accounts/', include('allauth.urls')), path('i18n/', include('django.conf.urls.i18n')), path('admin/', admin.site.urls), diff --git a/photologue_custom/urls.py b/photologue/urls.py similarity index 73% rename from photologue_custom/urls.py rename to photologue/urls.py index 037a354..4772067 100644 --- a/photologue_custom/urls.py +++ b/photologue/urls.py @@ -1,10 +1,8 @@ from django.urls import path, re_path -from photologue.views import GalleryArchiveIndexView, GalleryYearArchiveView, PhotoDetailView +from photologue_custom.views import CustomGalleryDetailView, GalleryDownload, GalleryUpload, TagDetail -from .views import CustomGalleryDetailView, GalleryDownload, GalleryUpload, TagDetail +from .views import GalleryArchiveIndexView, GalleryYearArchiveView, PhotoDetailView -# Rather than using photologue default router, we redefine our own router -# with login and permission checks. app_name = 'photologue' urlpatterns = [ path('tag/<slug:slug>/', TagDetail.as_view(), name='tag-detail'), -- GitLab From 3bc8a2b649dc8cc36a57625768c119a8d95ffcae Mon Sep 17 00:00:00 2001 From: Alexandre Iooss <erdnaxe@crans.org> Date: Sun, 30 Jan 2022 10:21:23 +0100 Subject: [PATCH 4/9] Remove padding around thumbnails --- photologue_custom/templates/photologue/gallery_detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/photologue_custom/templates/photologue/gallery_detail.html b/photologue_custom/templates/photologue/gallery_detail.html index 21bc348..9649dc7 100644 --- a/photologue_custom/templates/photologue/gallery_detail.html +++ b/photologue_custom/templates/photologue/gallery_detail.html @@ -70,7 +70,7 @@ SPDX-License-Identifier: GPL-3.0-or-later <div class="card-body row" id="lightgallery"> {% 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 }}"> - <img src="{{ photo.get_thumbnail_url }}" loading="lazy" class="img-thumbnail" 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.extended.owner.get_full_name }}{% if photo.extended.license %} - {{ photo.extended.license }}{% endif %}"> </a> {% endfor %} </div> -- GitLab From 8beedb36264d75cf01d7dd34076a1ddf2b0438c1 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss <erdnaxe@crans.org> Date: Sun, 30 Jan 2022 10:53:58 +0100 Subject: [PATCH 5/9] Remove extended models --- README.md | 3 +- photologue/admin.py | 12 +++- photologue/models.py | 2 +- photologue/views.py | 2 +- photologue_custom/admin.py | 47 -------------- photologue_custom/forms.py | 24 ++----- .../management/commands/rename_media.py | 2 +- .../migrations/0005_auto_20220130_0953.py | 27 ++++++++ photologue_custom/models.py | 64 ------------------- .../templates/photologue/gallery_detail.html | 8 +-- .../photologue/includes/gallery_sample.html | 2 +- .../{taggit => photologue}/tag_detail.html | 0 photologue_custom/views.py | 27 ++++---- requirements.txt | 1 - 14 files changed, 66 insertions(+), 155 deletions(-) delete mode 100644 photologue_custom/admin.py create mode 100644 photologue_custom/migrations/0005_auto_20220130_0953.py delete mode 100644 photologue_custom/models.py rename photologue_custom/templates/{taggit => photologue}/tag_detail.html (100%) diff --git a/README.md b/README.md index 52dccb3..9edddbc 100644 --- a/README.md +++ b/README.md @@ -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 \ python3-certbot-nginx python3-django python3-django-crispy-forms \ - python3-django-taggit python3-pil python3-exifread python3-django-allauth \ - python3-psycopg2 python3-docutils + python3-pil python3-exifread python3-django-allauth python3-docutils ``` 2. **Clonage du dépot dans `/var/www/photos/photo21`** diff --git a/photologue/admin.py b/photologue/admin.py index ff797fb..f398fc7 100644 --- a/photologue/admin.py +++ b/photologue/admin.py @@ -1,4 +1,5 @@ from django.contrib import admin +from django.utils.translation import gettext_lazy as _ from .models import Gallery, Photo, Tag @@ -15,14 +16,19 @@ class GalleryAdmin(admin.ModelAdmin): class PhotoAdmin(admin.ModelAdmin): list_display = ('title', 'date_taken', 'date_added', - 'is_public', 'view_count', 'admin_thumbnail') - list_filter = ['date_added', 'is_public'] + 'is_public', 'view_count', 'admin_thumbnail', 'get_owner') + list_filter = ['date_added', 'is_public', 'owner'] search_fields = ['title', 'slug', 'caption'] list_per_page = 10 prepopulated_fields = {'slug': ('title',)} readonly_fields = ('date_taken',) 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): list_display = ('name',) @@ -30,4 +36,6 @@ class TagAdmin(admin.ModelAdmin): model = Tag +admin.site.register(Gallery, GalleryAdmin) +admin.site.register(Photo, PhotoAdmin) admin.site.register(Tag, TagAdmin) diff --git a/photologue/models.py b/photologue/models.py index 059ac44..8b94e5c 100644 --- a/photologue/models.py +++ b/photologue/models.py @@ -178,7 +178,7 @@ class Gallery(models.Model): verbose_name_plural = _('galleries') def __str__(self): - return self.title + return f"{ self.title } ({self.date_start})" def get_absolute_url(self): return reverse('photologue:pl-gallery', args=[self.slug]) diff --git a/photologue/views.py b/photologue/views.py index 93fc8b5..2741b50 100644 --- a/photologue/views.py +++ b/photologue/views.py @@ -7,7 +7,7 @@ from .models import Gallery, Photo class GalleryDateView(LoginRequiredMixin): queryset = Gallery.objects.filter(is_public=True) - date_field = 'extended__date_start' + date_field = 'date_start' uses_datetime_field = False # Fix related object access allow_empty = True diff --git a/photologue_custom/admin.py b/photologue_custom/admin.py deleted file mode 100644 index e8f0130..0000000 --- a/photologue_custom/admin.py +++ /dev/null @@ -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) diff --git a/photologue_custom/forms.py b/photologue_custom/forms.py index 11a146d..96f4498 100644 --- a/photologue_custom/forms.py +++ b/photologue_custom/forms.py @@ -5,19 +5,7 @@ from crispy_forms.layout import Div, Layout, Submit from django import forms from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ -from photologue.models import Gallery -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 +from photologue.models import Gallery, Tag class UploadForm(forms.Form): @@ -29,7 +17,7 @@ class UploadForm(forms.Form): 'class': 'mb-3', }), ) - gallery = GalleryChoiceField( + gallery = forms.ModelChoiceField( Gallery.objects.all(), label=_('Gallery'), required=False, @@ -100,12 +88,12 @@ class UploadForm(forms.Form): if not gallery: # Create new gallery title = self.cleaned_data.get('new_gallery_title') - gallery = Gallery.objects.create(title=title, slug=slugify(title)) - ext = GalleryExtended.objects.create( - gallery=gallery, + gallery = Gallery.objects.create( + title=title, + slug=slugify(title), date_start=self.cleaned_data['new_gallery_date_start'], date_end=self.cleaned_data['new_gallery_date_end'], ) for tag in self.cleaned_data['new_gallery_tags']: - ext.tags.add(tag) + gallery.tags.add(tag) return gallery diff --git a/photologue_custom/management/commands/rename_media.py b/photologue_custom/management/commands/rename_media.py index 62615e9..461870b 100644 --- a/photologue_custom/management/commands/rename_media.py +++ b/photologue_custom/management/commands/rename_media.py @@ -16,7 +16,7 @@ class Command(BaseCommand): media_dir = Path(settings.MEDIA_ROOT) for gallery in Gallery.objects.all(): # 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_path = media_dir / gallery_dir if not gallery_path.exists(): diff --git a/photologue_custom/migrations/0005_auto_20220130_0953.py b/photologue_custom/migrations/0005_auto_20220130_0953.py new file mode 100644 index 0000000..ef769ec --- /dev/null +++ b/photologue_custom/migrations/0005_auto_20220130_0953.py @@ -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', + ), + ] diff --git a/photologue_custom/models.py b/photologue_custom/models.py deleted file mode 100644 index 6275e64..0000000 --- a/photologue_custom/models.py +++ /dev/null @@ -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) diff --git a/photologue_custom/templates/photologue/gallery_detail.html b/photologue_custom/templates/photologue/gallery_detail.html index 9649dc7..1df68af 100644 --- a/photologue_custom/templates/photologue/gallery_detail.html +++ b/photologue_custom/templates/photologue/gallery_detail.html @@ -38,10 +38,10 @@ SPDX-License-Identifier: GPL-3.0-or-later </a> {% endif %} </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.extended.tags.all %} +{% 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.tags.all %} <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> {% endfor %} </p> @@ -70,7 +70,7 @@ SPDX-License-Identifier: GPL-3.0-or-later <div class="card-body row" id="lightgallery"> {% 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 }}"> - <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> {% endfor %} </div> diff --git a/photologue_custom/templates/photologue/includes/gallery_sample.html b/photologue_custom/templates/photologue/includes/gallery_sample.html index abe2bfd..8282074 100644 --- a/photologue_custom/templates/photologue/includes/gallery_sample.html +++ b/photologue_custom/templates/photologue/includes/gallery_sample.html @@ -6,7 +6,7 @@ {% endfor %} <div class="card-body"> <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> </div> </div> diff --git a/photologue_custom/templates/taggit/tag_detail.html b/photologue_custom/templates/photologue/tag_detail.html similarity index 100% rename from photologue_custom/templates/taggit/tag_detail.html rename to photologue_custom/templates/photologue/tag_detail.html diff --git a/photologue_custom/views.py b/photologue_custom/views.py index 8a683f0..38ebc7f 100644 --- a/photologue_custom/views.py +++ b/photologue_custom/views.py @@ -16,12 +16,10 @@ from django.urls import reverse_lazy from django.utils.text import slugify from django.views.generic.detail import DetailView 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 taggit.models import Tag from .forms import UploadForm -from .models import PhotoExtended class TagDetail(LoginRequiredMixin, DetailView): @@ -34,8 +32,8 @@ class TagDetail(LoginRequiredMixin, DetailView): current_tag = self.get_object().slug context = super().get_context_data(**kwargs) context['galleries'] = Gallery.objects.filter(is_public=True) \ - .filter(extended__tags__slug=current_tag) \ - .order_by('-extended__date_start') + .filter(tags__slug=current_tag) \ + .order_by('-date_start') return context @@ -48,18 +46,18 @@ class CustomGalleryDetailView(LoginRequiredMixin, DetailView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - # Query with extended and owner to reduce database lag - context['photos'] = self.object.public().select_related('extended__owner') + # Query with owner to reduce database lag + context['photos'] = self.object.public().select_related('owner') # List owners context['owners'] = [] for photo in context['photos']: - if hasattr(photo, 'extended') and photo.extended.owner not in context['owners']: - context['owners'].append(photo.extended.owner) + if photo.owner not in context['owners']: + context['owners'].append(photo.owner) # Filter on owner 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 @@ -100,7 +98,7 @@ class GalleryUpload(PermissionRequiredMixin, FormView): # We take files from the request to support multiple upload files = self.request.FILES.getlist('file_field') 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 failed_upload = 0 for photo_file in files: @@ -116,12 +114,15 @@ class GalleryUpload(PermissionRequiredMixin, FormView): title = f"{gallery.title} - {photo_file.name}" 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.image.save(photo_name, photo_file) photo.save() photo.galleries.set([gallery]) - PhotoExtended.objects.create(photo=photo, owner=self.request.user) except IntegrityError: messages.error(self.request, f"{photo_file.name} was not uploaded. Maybe the photo was already uploaded.") failed_upload += 1 diff --git a/requirements.txt b/requirements.txt index 9f86e8d..cf9dcaf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,5 @@ django-allauth>=0.44 django-crispy-forms~=1.7 -django-taggit>=1.5.0 Django>=2.2.20 ExifRead>=2.1.2 git+https://gitlab.crans.org/bde/allauth-note-kfet.git -- GitLab From d865a6eb1f99004e94da9093009afced4b436a85 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss <erdnaxe@crans.org> Date: Sun, 30 Jan 2022 11:09:55 +0100 Subject: [PATCH 6/9] Merge photologue_custom into photologue --- photo21/locale/de/LC_MESSAGES/django.po | 20 +- photo21/locale/es/LC_MESSAGES/django.po | 20 +- photo21/locale/fr/LC_MESSAGES/django.po | 67 +--- photo21/settings.py | 1 - {photologue_custom => photologue}/forms.py | 3 +- photologue/locale/de/LC_MESSAGES/django.po | 194 +++++------ photologue/locale/es/LC_MESSAGES/django.po | 194 +++++------ photologue/locale/fr/LC_MESSAGES/django.po | 307 +++++++++--------- .../management/commands/duplicate.py | 4 +- .../management/commands/rename_media.py | 4 +- photologue/migrations/0014_merge_related.py | 4 +- .../static/lightgallery/css/lg-thumbnail.css | 0 .../static/lightgallery/css/lg-zoom.css | 0 .../static/lightgallery/css/lightgallery.css | 0 .../static/lightgallery/fonts/lg.svg | 0 .../static/lightgallery/fonts/lg.ttf | Bin .../static/lightgallery/fonts/lg.woff | Bin .../static/lightgallery/fonts/lg.woff2 | Bin .../static/lightgallery/images/loading.gif | Bin .../static/lightgallery/lightgallery.min.js | 0 .../lightgallery/plugins/admin/lg-admin.js | 0 .../lightgallery/plugins/hash/lg-hash.min.js | 0 .../plugins/thumbnail/lg-thumbnail.min.js | 0 .../lightgallery/plugins/zoom/lg-zoom.min.js | 0 .../admin/photologue/photo/change_list.html | 0 .../templates/photologue/gallery_archive.html | 0 .../photologue/gallery_archive_year.html | 0 .../templates/photologue/gallery_detail.html | 0 .../photologue/includes/gallery_sample.html | 0 .../templates/photologue/photo_detail.html | 0 .../templates/photologue/tag_detail.html | 0 .../templates/photologue/upload.html | 0 photologue/urls.py | 5 +- photologue/views.py | 144 +++++++- photologue_custom/views.py | 144 -------- tox.ini | 4 +- 36 files changed, 549 insertions(+), 566 deletions(-) rename {photologue_custom => photologue}/forms.py (98%) rename {photologue_custom => photologue}/management/commands/duplicate.py (100%) rename {photologue_custom => photologue}/management/commands/rename_media.py (100%) rename {photologue_custom => photologue}/static/lightgallery/css/lg-thumbnail.css (100%) rename {photologue_custom => photologue}/static/lightgallery/css/lg-zoom.css (100%) rename {photologue_custom => photologue}/static/lightgallery/css/lightgallery.css (100%) rename {photologue_custom => photologue}/static/lightgallery/fonts/lg.svg (100%) rename {photologue_custom => photologue}/static/lightgallery/fonts/lg.ttf (100%) rename {photologue_custom => photologue}/static/lightgallery/fonts/lg.woff (100%) rename {photologue_custom => photologue}/static/lightgallery/fonts/lg.woff2 (100%) rename {photologue_custom => photologue}/static/lightgallery/images/loading.gif (100%) rename {photologue_custom => photologue}/static/lightgallery/lightgallery.min.js (100%) rename {photologue_custom => photologue}/static/lightgallery/plugins/admin/lg-admin.js (100%) rename {photologue_custom => photologue}/static/lightgallery/plugins/hash/lg-hash.min.js (100%) rename {photologue_custom => photologue}/static/lightgallery/plugins/thumbnail/lg-thumbnail.min.js (100%) rename {photologue_custom => photologue}/static/lightgallery/plugins/zoom/lg-zoom.min.js (100%) rename {photologue_custom => photologue}/templates/admin/photologue/photo/change_list.html (100%) rename {photologue_custom => photologue}/templates/photologue/gallery_archive.html (100%) rename {photologue_custom => photologue}/templates/photologue/gallery_archive_year.html (100%) rename {photologue_custom => photologue}/templates/photologue/gallery_detail.html (100%) rename {photologue_custom => photologue}/templates/photologue/includes/gallery_sample.html (100%) rename {photologue_custom => photologue}/templates/photologue/photo_detail.html (100%) rename {photologue_custom => photologue}/templates/photologue/tag_detail.html (100%) rename {photologue_custom => photologue}/templates/photologue/upload.html (100%) delete mode 100644 photologue_custom/views.py diff --git a/photo21/locale/de/LC_MESSAGES/django.po b/photo21/locale/de/LC_MESSAGES/django.po index 1cff806..d45572b 100644 --- a/photo21/locale/de/LC_MESSAGES/django.po +++ b/photo21/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-01-29 21:58+0000\n" +"POT-Creation-Date: 2022-01-30 09:55+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -40,19 +40,19 @@ msgstr "" msgid "hash" msgstr "" -#: photo21/settings.py:162 +#: photo21/settings.py:161 msgid "German" msgstr "" -#: photo21/settings.py:163 +#: photo21/settings.py:162 msgid "English" msgstr "" -#: photo21/settings.py:164 +#: photo21/settings.py:163 msgid "Spanish" msgstr "" -#: photo21/settings.py:165 +#: photo21/settings.py:164 msgid "French" msgstr "" @@ -199,6 +199,16 @@ msgstr "" msgid "If any problem, please contact the server owners at" msgstr "" +#: photo21/templates/account/logout.html:6 +#: photo21/templates/account/logout.html:11 +#: photo21/templates/account/logout.html:20 +msgid "Sign Out" +msgstr "" + +#: photo21/templates/account/logout.html:14 +msgid "Are you sure you want to sign out?" +msgstr "" + #: photo21/templates/account/signup.html:6 msgid "Signup" msgstr "" diff --git a/photo21/locale/es/LC_MESSAGES/django.po b/photo21/locale/es/LC_MESSAGES/django.po index a9413d9..f05fed8 100644 --- a/photo21/locale/es/LC_MESSAGES/django.po +++ b/photo21/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-01-29 21:58+0000\n" +"POT-Creation-Date: 2022-01-30 09:55+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -39,19 +39,19 @@ msgstr "" msgid "hash" msgstr "" -#: photo21/settings.py:162 +#: photo21/settings.py:161 msgid "German" msgstr "" -#: photo21/settings.py:163 +#: photo21/settings.py:162 msgid "English" msgstr "" -#: photo21/settings.py:164 +#: photo21/settings.py:163 msgid "Spanish" msgstr "" -#: photo21/settings.py:165 +#: photo21/settings.py:164 msgid "French" msgstr "" @@ -198,6 +198,16 @@ msgstr "" msgid "If any problem, please contact the server owners at" msgstr "" +#: photo21/templates/account/logout.html:6 +#: photo21/templates/account/logout.html:11 +#: photo21/templates/account/logout.html:20 +msgid "Sign Out" +msgstr "" + +#: photo21/templates/account/logout.html:14 +msgid "Are you sure you want to sign out?" +msgstr "" + #: photo21/templates/account/signup.html:6 msgid "Signup" msgstr "" diff --git a/photo21/locale/fr/LC_MESSAGES/django.po b/photo21/locale/fr/LC_MESSAGES/django.po index ac7970b..7d7d518 100644 --- a/photo21/locale/fr/LC_MESSAGES/django.po +++ b/photo21/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-01-30 07:09+0000\n" +"POT-Creation-Date: 2022-01-30 10:06+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -42,19 +42,19 @@ msgstr "" msgid "hash" msgstr "" -#: photo21/settings.py:162 +#: photo21/settings.py:160 msgid "German" msgstr "" -#: photo21/settings.py:163 +#: photo21/settings.py:161 msgid "English" msgstr "" -#: photo21/settings.py:164 +#: photo21/settings.py:162 msgid "Spanish" msgstr "" -#: photo21/settings.py:165 +#: photo21/settings.py:163 msgid "French" msgstr "" @@ -206,6 +206,18 @@ msgstr "" msgid "If any problem, please contact the server owners at" msgstr "En cas de problème, contactez les administrateurs à " +#: photo21/templates/account/logout.html:6 +#: photo21/templates/account/logout.html:11 +#: photo21/templates/account/logout.html:20 +#, fuzzy +#| msgid "Sign up" +msgid "Sign Out" +msgstr "Inscription" + +#: photo21/templates/account/logout.html:14 +msgid "Are you sure you want to sign out?" +msgstr "" + #: photo21/templates/account/signup.html:6 msgid "Signup" msgstr "" @@ -333,48 +345,3 @@ msgstr "" #: photo21/templates/socialaccount/connections.html:54 msgid "Add a 3rd Party Account" msgstr "" - -#~ msgid "owner" -#~ msgstr "propriétaire" - -#~ msgid "Gallery" -#~ msgstr "Galerie" - -#~ msgid "-- Create a new gallery --" -#~ msgstr "-- Créer une nouvelle galerie --" - -#~ msgid "New gallery title" -#~ msgstr "Titre de la nouvelle galerie" - -#~ msgid "New gallery event start date" -#~ msgstr "Date de début de l'évènement de la nouvelle galerie" - -#~ msgid "New gallery event end date" -#~ msgstr "Date de fin de l'évènement de la nouvelle galerie" - -#~ msgid "New gallery tags" -#~ msgstr "Tags de la nouvelle galerie" - -#~ msgid "start date" -#~ msgstr "date de début" - -#~ msgid "end date" -#~ msgstr "date de fin" - -#~ msgid "license" -#~ msgstr "licence" - -#~ msgid "to" -#~ msgstr "au" - -#~ msgid "All pictures" -#~ msgstr "Toutes les photos" - -#~ msgid "Download all gallery" -#~ msgstr "Télécharger toute la galerie" - -#~ msgid "Drag and drop photos here" -#~ msgstr "Glissez et déposez les photos ici" - -#~ msgid "Owner will be" -#~ msgstr "Le propriétaire sera" diff --git a/photo21/settings.py b/photo21/settings.py index 5c61f42..9b2844b 100644 --- a/photo21/settings.py +++ b/photo21/settings.py @@ -62,7 +62,6 @@ INSTALLED_APPS = [ 'allauth.socialaccount', 'allauth_note_kfet', 'crispy_forms', - 'photologue_custom', 'photologue', 'taggit', ] diff --git a/photologue_custom/forms.py b/photologue/forms.py similarity index 98% rename from photologue_custom/forms.py rename to photologue/forms.py index 96f4498..8ef1f1c 100644 --- a/photologue_custom/forms.py +++ b/photologue/forms.py @@ -5,7 +5,8 @@ from crispy_forms.layout import Div, Layout, Submit from django import forms from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ -from photologue.models import Gallery, Tag + +from .models import Gallery, Tag class UploadForm(forms.Form): diff --git a/photologue/locale/de/LC_MESSAGES/django.po b/photologue/locale/de/LC_MESSAGES/django.po index f9a29ed..50c106d 100644 --- a/photologue/locale/de/LC_MESSAGES/django.po +++ b/photologue/locale/de/LC_MESSAGES/django.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: Photologue\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-01-30 07:09+0000\n" +"POT-Creation-Date: 2022-01-30 09:55+0000\n" "PO-Revision-Date: 2017-12-03 14:47+0000\n" "Last-Translator: Richard Barran <richard@arbee-design.co.uk>\n" "Language-Team: German (http://www.transifex.com/richardbarran/django-" @@ -22,75 +22,79 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: photologue/models.py:86 +#: photologue/admin.py:30 photologue/models.py:499 +msgid "owner" +msgstr "" + +#: photologue/models.py:84 msgid "Very Low" msgstr "Sehr niedrig" -#: photologue/models.py:87 +#: photologue/models.py:85 msgid "Low" msgstr "Niedrig" -#: photologue/models.py:88 +#: photologue/models.py:86 msgid "Medium-Low" msgstr "Mittel-niedrig" -#: photologue/models.py:89 +#: photologue/models.py:87 msgid "Medium" msgstr "Mittel" -#: photologue/models.py:90 +#: photologue/models.py:88 msgid "Medium-High" msgstr "Mittel-hoch" -#: photologue/models.py:91 +#: photologue/models.py:89 msgid "High" msgstr "Hoch" -#: photologue/models.py:92 +#: photologue/models.py:90 msgid "Very High" msgstr "Sehr hoch" -#: photologue/models.py:97 +#: photologue/models.py:95 msgid "Top" msgstr "Oben" -#: photologue/models.py:98 +#: photologue/models.py:96 msgid "Right" msgstr "Rechts" -#: photologue/models.py:99 +#: photologue/models.py:97 msgid "Bottom" msgstr "Unten" -#: photologue/models.py:100 +#: photologue/models.py:98 msgid "Left" msgstr "Links" -#: photologue/models.py:101 +#: photologue/models.py:99 msgid "Center (Default)" msgstr "Mitte (Standard)" -#: photologue/models.py:105 +#: photologue/models.py:103 msgid "Flip left to right" msgstr "Horizontal spiegeln" -#: photologue/models.py:106 +#: photologue/models.py:104 msgid "Flip top to bottom" msgstr "Vertikal spiegeln" -#: photologue/models.py:107 +#: photologue/models.py:105 msgid "Rotate 90 degrees counter-clockwise" msgstr "Um 90° nach links drehen" -#: photologue/models.py:108 +#: photologue/models.py:106 msgid "Rotate 90 degrees clockwise" msgstr "Um 90° nach rechts drehen" -#: photologue/models.py:109 +#: photologue/models.py:107 msgid "Rotate 180 degrees" msgstr "Um 180° drehen" -#: photologue/models.py:119 +#: photologue/models.py:117 #, python-format msgid "" "Chain multiple filters using the following pattern \"FILTER_ONE->FILTER_TWO-" @@ -101,106 +105,122 @@ msgstr "" "\". Bildfilter werden nach der Reihe angewendet. Folgende Filter sind " "verfügbar: %s." -#: photologue/models.py:141 +#: photologue/models.py:139 msgid "date published" msgstr "Veröffentlichungsdatum" -#: photologue/models.py:143 photologue/models.py:474 +#: photologue/models.py:141 photologue/models.py:485 msgid "title" msgstr "Titel" -#: photologue/models.py:146 +#: photologue/models.py:144 msgid "title slug" msgstr "Kurztitel" -#: photologue/models.py:149 photologue/models.py:480 +#: photologue/models.py:147 photologue/models.py:491 photologue/models.py:697 msgid "A \"slug\" is a unique URL-friendly title for an object." msgstr "" "Ein Kurztitel (\"slug\") ist ein eindeutiger, URL-geeigneter Titel für ein " "Objekt." #: photologue/models.py:150 +msgid "start date" +msgstr "" + +#: photologue/models.py:155 +msgid "end date" +msgstr "" + +#: photologue/models.py:157 msgid "description" msgstr "Beschreibung" -#: photologue/models.py:152 photologue/models.py:485 +#: photologue/models.py:162 photologue/models.py:703 +msgid "tags" +msgstr "" + +#: photologue/models.py:165 photologue/models.py:506 msgid "is public" msgstr "ist öffentlich" -#: photologue/models.py:154 +#: photologue/models.py:167 msgid "Public galleries will be displayed in the default views." msgstr "Öffentliche Galerien werden in den Standard-Views angezeigt." -#: photologue/models.py:158 photologue/models.py:495 +#: photologue/models.py:171 photologue/models.py:514 msgid "photos" msgstr "Fotos" -#: photologue/models.py:166 +#: photologue/models.py:177 msgid "gallery" msgstr "Galerie" -#: photologue/models.py:167 +#: photologue/models.py:178 msgid "galleries" msgstr "Galerien" -#: photologue/models.py:202 +#: photologue/models.py:213 msgid "count" msgstr "Anzahl" -#: photologue/models.py:210 +#: photologue/models.py:221 msgid "image" msgstr "Bild" -#: photologue/models.py:213 +#: photologue/models.py:224 msgid "date taken" msgstr "Aufnahmedatum" -#: photologue/models.py:216 +#: photologue/models.py:227 msgid "Date image was taken; is obtained from the image EXIF data." msgstr "" "Datum, an dem das Foto geschossen wurde; ausgelesen aus den EXIF-Daten." -#: photologue/models.py:217 +#: photologue/models.py:228 msgid "view count" msgstr "Anzahl an Aufrufen" -#: photologue/models.py:220 +#: photologue/models.py:231 msgid "crop from" msgstr "Beschneiden von" -#: photologue/models.py:243 +#: photologue/models.py:254 msgid "An \"admin_thumbnail\" photo size has not been defined." msgstr "Es ist keine Fotogröße \"admin_thumbnail\" definiert." -#: photologue/models.py:250 +#: photologue/models.py:261 msgid "Thumbnail" msgstr "Vorschaubild" -#: photologue/models.py:477 +#: photologue/models.py:488 photologue/models.py:696 msgid "slug" msgstr "Kurztitel" -#: photologue/models.py:481 +#: photologue/models.py:492 msgid "caption" msgstr "Bildunterschrift" -#: photologue/models.py:483 +#: photologue/models.py:494 msgid "date added" msgstr "Datum des Eintrags" -#: photologue/models.py:487 +#: photologue/models.py:504 +msgid "license" +msgstr "" + +#: photologue/models.py:508 msgid "Public photographs will be displayed in the default views." msgstr "Öffentliche Fotos werden in den Standard-Views angezeigt." -#: photologue/models.py:494 +#: photologue/models.py:513 msgid "photo" msgstr "Foto" -#: photologue/models.py:556 +#: photologue/models.py:575 photologue/models.py:691 msgid "name" msgstr "Name" -#: photologue/models.py:560 +#: photologue/models.py:579 msgid "" "Photo size name should contain only letters, numbers and underscores. " "Examples: \"thumbnail\", \"display\", \"small\", \"main_page_widget\"." @@ -209,41 +229,41 @@ msgstr "" "enthalten. Beispiele: \"thumbnail\", \"display\", \"small\", " "\"main_page_widget\"." -#: photologue/models.py:567 +#: photologue/models.py:586 msgid "width" msgstr "Breite" -#: photologue/models.py:570 +#: photologue/models.py:589 msgid "" "If width is set to \"0\" the image will be scaled to the supplied height." msgstr "" "Wenn die Breite auf \"0\" gesetzt ist, wird das Bild proportional auf die " "angebene Höhe skaliert." -#: photologue/models.py:571 +#: photologue/models.py:590 msgid "height" msgstr "Höhe" -#: photologue/models.py:574 +#: photologue/models.py:593 msgid "" "If height is set to \"0\" the image will be scaled to the supplied width" msgstr "" "Wenn die Höhe auf \"0\" gesetzt ist, wird das Bild proportional auf die " "angebene Breite skaliert." -#: photologue/models.py:575 +#: photologue/models.py:594 msgid "quality" msgstr "Qualität" -#: photologue/models.py:578 +#: photologue/models.py:597 msgid "JPEG image quality." msgstr "JPEG-Bildqualität" -#: photologue/models.py:579 +#: photologue/models.py:598 msgid "upscale images?" msgstr "Bilder hochskalieren?" -#: photologue/models.py:581 +#: photologue/models.py:600 msgid "" "If selected the image will be scaled up if necessary to fit the supplied " "dimensions. Cropped sizes will be upscaled regardless of this setting." @@ -252,32 +272,32 @@ msgstr "" "Beschnittene Größen werden unabhängig von dieser Einstellung bei Bedarf " "hochskaliert." -#: photologue/models.py:585 +#: photologue/models.py:604 msgid "crop to fit?" msgstr "Zuschneiden?" -#: photologue/models.py:587 +#: photologue/models.py:606 msgid "" "If selected the image will be scaled and cropped to fit the supplied " "dimensions." msgstr "" "Soll das Bild auf das angegebene Format skaliert und beschnitten werden?" -#: photologue/models.py:589 +#: photologue/models.py:608 msgid "pre-cache?" msgstr "Vorausspeichern?" -#: photologue/models.py:591 +#: photologue/models.py:610 msgid "If selected this photo size will be pre-cached as photos are added." msgstr "" "Soll diese Bildgröße im Voraus gespeichert (pre-cached) werden, wenn Fotos " "hinzugefügt werden?" -#: photologue/models.py:592 +#: photologue/models.py:611 msgid "increment view count?" msgstr "Bildzähler?" -#: photologue/models.py:594 +#: photologue/models.py:613 msgid "" "If selected the image's \"view_count\" will be incremented when this photo " "size is displayed." @@ -285,32 +305,32 @@ msgstr "" "Soll der Ansichts-Zähler (view-count) hochgezählt werden, wenn ein Foto " "dieser Größe angezeigt wird?" -#: photologue/models.py:599 +#: photologue/models.py:618 msgid "photo size" msgstr "Foto-Größe" -#: photologue/models.py:600 +#: photologue/models.py:619 msgid "photo sizes" msgstr "Foto-Größen" -#: photologue/models.py:617 +#: photologue/models.py:636 msgid "Can only crop photos if both width and height dimensions are set." msgstr "" "Fotos können nur zugeschnitten werden, wenn Breite und Höhe angegeben sind." -#: photologue_custom/admin.py:43 photologue_custom/models.py:51 -msgid "owner" +#: photologue/models.py:702 +msgid "tag" msgstr "" -#: photologue_custom/forms.py:34 +#: photologue_custom/forms.py:22 msgid "Gallery" msgstr "Galerie" -#: photologue_custom/forms.py:36 +#: photologue_custom/forms.py:24 msgid "-- Create a new gallery --" msgstr "" -#: photologue_custom/forms.py:37 +#: photologue_custom/forms.py:25 msgid "" "Select a gallery to add these images to. Leave this empty to create a new " "gallery from the supplied title." @@ -318,59 +338,43 @@ msgstr "" "Wähle eine Galerie aus, zu der diese Bilder hinzugefügt werden sollen. Lasse " "dieses Feld leer, um eine neue Galerie mit dem angegeben Titel zu erzeugen." -#: photologue_custom/forms.py:41 -#, fuzzy -#| msgid "View all galleries" +#: photologue_custom/forms.py:29 msgid "New gallery title" -msgstr "Zeige alle Galerien." +msgstr "" -#: photologue_custom/forms.py:46 +#: photologue_custom/forms.py:34 msgid "New gallery event start date" msgstr "" -#: photologue_custom/forms.py:51 +#: photologue_custom/forms.py:39 msgid "New gallery event end date" msgstr "" -#: photologue_custom/forms.py:57 -#, fuzzy -#| msgid "gallery" +#: photologue_custom/forms.py:45 msgid "New gallery tags" -msgstr "Galerie" +msgstr "" -#: photologue_custom/forms.py:59 +#: photologue_custom/forms.py:47 msgid "" "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." msgstr "" -#: photologue_custom/forms.py:76 +#: photologue_custom/forms.py:64 #: photologue_custom/templates/photologue/upload.html:6 #: photologue_custom/templates/photologue/upload.html:73 msgid "Upload" msgstr "Hochladen" -#: photologue_custom/forms.py:82 +#: photologue_custom/forms.py:70 msgid "A gallery with that title already exists." msgstr "Es existiert bereits eine Gallerie mit diesem Titel." -#: photologue_custom/forms.py:91 +#: photologue_custom/forms.py:79 msgid "Select an existing gallery, or enter a title for a new gallery." msgstr "" "Wähle eine existierende Galerie aus oder gib einen Titel für eine neue " "Galerie ein." -#: photologue_custom/models.py:23 -msgid "start date" -msgstr "" - -#: photologue_custom/models.py:28 -msgid "end date" -msgstr "" - -#: photologue_custom/models.py:56 -msgid "license" -msgstr "" - #: photologue_custom/templates/photologue/gallery_archive.html:7 #: photologue_custom/templates/photologue/gallery_archive.html:12 msgid "Latest photo galleries" @@ -403,16 +407,12 @@ msgid "to" msgstr "" #: photologue_custom/templates/photologue/gallery_detail.html:57 -#, fuzzy -#| msgid "All photos" msgid "All pictures" -msgstr "Alle Fotos" +msgstr "" #: photologue_custom/templates/photologue/gallery_detail.html:78 -#, fuzzy -#| msgid "View all galleries" msgid "Download all gallery" -msgstr "Zeige alle Galerien." +msgstr "" #: photologue_custom/templates/photologue/photo_detail.html:13 msgid "Published" diff --git a/photologue/locale/es/LC_MESSAGES/django.po b/photologue/locale/es/LC_MESSAGES/django.po index 8a9ca71..e8f687f 100644 --- a/photologue/locale/es/LC_MESSAGES/django.po +++ b/photologue/locale/es/LC_MESSAGES/django.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: Photologue\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-01-30 07:09+0000\n" +"POT-Creation-Date: 2022-01-30 09:55+0000\n" "PO-Revision-Date: 2017-12-03 14:46+0000\n" "Last-Translator: Richard Barran <richard@arbee-design.co.uk>\n" "Language-Team: Spanish (Spain) (http://www.transifex.com/richardbarran/" @@ -23,75 +23,79 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: photologue/models.py:86 +#: photologue/admin.py:30 photologue/models.py:499 +msgid "owner" +msgstr "" + +#: photologue/models.py:84 msgid "Very Low" msgstr "Muy bajo" -#: photologue/models.py:87 +#: photologue/models.py:85 msgid "Low" msgstr "Bajo" -#: photologue/models.py:88 +#: photologue/models.py:86 msgid "Medium-Low" msgstr "Medio-bajo" -#: photologue/models.py:89 +#: photologue/models.py:87 msgid "Medium" msgstr "Medio" -#: photologue/models.py:90 +#: photologue/models.py:88 msgid "Medium-High" msgstr "Medio-alto" -#: photologue/models.py:91 +#: photologue/models.py:89 msgid "High" msgstr "Alto" -#: photologue/models.py:92 +#: photologue/models.py:90 msgid "Very High" msgstr "Muy alto" -#: photologue/models.py:97 +#: photologue/models.py:95 msgid "Top" msgstr "Arriba" -#: photologue/models.py:98 +#: photologue/models.py:96 msgid "Right" msgstr "Derecha" -#: photologue/models.py:99 +#: photologue/models.py:97 msgid "Bottom" msgstr "Abajo" -#: photologue/models.py:100 +#: photologue/models.py:98 msgid "Left" msgstr "Izquierda" -#: photologue/models.py:101 +#: photologue/models.py:99 msgid "Center (Default)" msgstr "Centro (por defecto)" -#: photologue/models.py:105 +#: photologue/models.py:103 msgid "Flip left to right" msgstr "Voltear de izquerda a derecha" -#: photologue/models.py:106 +#: photologue/models.py:104 msgid "Flip top to bottom" msgstr "Voltear de arriba a abajo" -#: photologue/models.py:107 +#: photologue/models.py:105 msgid "Rotate 90 degrees counter-clockwise" msgstr "Rotar 90 grados en sentido horario" -#: photologue/models.py:108 +#: photologue/models.py:106 msgid "Rotate 90 degrees clockwise" msgstr "Rotar 90 grados en sentido antihorario" -#: photologue/models.py:109 +#: photologue/models.py:107 msgid "Rotate 180 degrees" msgstr "Rotar 180 grados" -#: photologue/models.py:119 +#: photologue/models.py:117 #, python-format msgid "" "Chain multiple filters using the following pattern \"FILTER_ONE->FILTER_TWO-" @@ -102,103 +106,119 @@ msgstr "" ">FILTRO_DOS->FILTRO_TRES\". Los filtros de imagen se aplicarán en orden. Los " "siguientes filtros están disponibles: %s." -#: photologue/models.py:141 +#: photologue/models.py:139 msgid "date published" msgstr "fecha de publicación" -#: photologue/models.py:143 photologue/models.py:474 +#: photologue/models.py:141 photologue/models.py:485 msgid "title" msgstr "tÃtulo" -#: photologue/models.py:146 +#: photologue/models.py:144 msgid "title slug" msgstr "tÃtulo slug" -#: photologue/models.py:149 photologue/models.py:480 +#: photologue/models.py:147 photologue/models.py:491 photologue/models.py:697 msgid "A \"slug\" is a unique URL-friendly title for an object." msgstr "Un \"slug\" es un único tÃtulo URL-amigable para un objeto." #: photologue/models.py:150 +msgid "start date" +msgstr "" + +#: photologue/models.py:155 +msgid "end date" +msgstr "" + +#: photologue/models.py:157 msgid "description" msgstr "descripción" -#: photologue/models.py:152 photologue/models.py:485 +#: photologue/models.py:162 photologue/models.py:703 +msgid "tags" +msgstr "" + +#: photologue/models.py:165 photologue/models.py:506 msgid "is public" msgstr "es público" -#: photologue/models.py:154 +#: photologue/models.py:167 msgid "Public galleries will be displayed in the default views." msgstr "Las galerÃas públicas serán mostradas en las vistas por defecto." -#: photologue/models.py:158 photologue/models.py:495 +#: photologue/models.py:171 photologue/models.py:514 msgid "photos" msgstr "fotos" -#: photologue/models.py:166 +#: photologue/models.py:177 msgid "gallery" msgstr "galerÃa" -#: photologue/models.py:167 +#: photologue/models.py:178 msgid "galleries" msgstr "galerÃas" -#: photologue/models.py:202 +#: photologue/models.py:213 msgid "count" msgstr "contar" -#: photologue/models.py:210 +#: photologue/models.py:221 msgid "image" msgstr "imagen" -#: photologue/models.py:213 +#: photologue/models.py:224 msgid "date taken" msgstr "fecha en la que se tomó" -#: photologue/models.py:216 +#: photologue/models.py:227 msgid "Date image was taken; is obtained from the image EXIF data." msgstr "La fecha de la imagen fue obtenida por información EXIF de la imagen." -#: photologue/models.py:217 +#: photologue/models.py:228 msgid "view count" msgstr "Contador de visitas" -#: photologue/models.py:220 +#: photologue/models.py:231 msgid "crop from" msgstr "Recortar desde" -#: photologue/models.py:243 +#: photologue/models.py:254 msgid "An \"admin_thumbnail\" photo size has not been defined." msgstr "El tamaño de foto de \"miniatura de admin\" no ha sido definido." -#: photologue/models.py:250 +#: photologue/models.py:261 msgid "Thumbnail" msgstr "Miniatura" -#: photologue/models.py:477 +#: photologue/models.py:488 photologue/models.py:696 msgid "slug" msgstr "slug" -#: photologue/models.py:481 +#: photologue/models.py:492 msgid "caption" msgstr "pie de foto" -#: photologue/models.py:483 +#: photologue/models.py:494 msgid "date added" msgstr "fecha añadida" -#: photologue/models.py:487 +#: photologue/models.py:504 +msgid "license" +msgstr "" + +#: photologue/models.py:508 msgid "Public photographs will be displayed in the default views." msgstr "Las fotos públicas serán mostradas en las vistas por defecto." -#: photologue/models.py:494 +#: photologue/models.py:513 msgid "photo" msgstr "foto" -#: photologue/models.py:556 +#: photologue/models.py:575 photologue/models.py:691 msgid "name" msgstr "nombre" -#: photologue/models.py:560 +#: photologue/models.py:579 msgid "" "Photo size name should contain only letters, numbers and underscores. " "Examples: \"thumbnail\", \"display\", \"small\", \"main_page_widget\"." @@ -206,41 +226,41 @@ msgstr "" "El nombre del tamaño solo puede contener letras, números y subrayados. Por " "ejemplo:\"miniaturas\", \"muestra\", \"muestra_principal\"." -#: photologue/models.py:567 +#: photologue/models.py:586 msgid "width" msgstr "anchura" -#: photologue/models.py:570 +#: photologue/models.py:589 msgid "" "If width is set to \"0\" the image will be scaled to the supplied height." msgstr "" "Si la anchura se establece a \"0\" la imagen será escalada hasta la altura " "proporcionada" -#: photologue/models.py:571 +#: photologue/models.py:590 msgid "height" msgstr "altura" -#: photologue/models.py:574 +#: photologue/models.py:593 msgid "" "If height is set to \"0\" the image will be scaled to the supplied width" msgstr "" "Si la altura se establece a \"0\" la imagen será escalada hasta la anchura " "proporcionada" -#: photologue/models.py:575 +#: photologue/models.py:594 msgid "quality" msgstr "calidad" -#: photologue/models.py:578 +#: photologue/models.py:597 msgid "JPEG image quality." msgstr "Calidad de imagen JPEG." -#: photologue/models.py:579 +#: photologue/models.py:598 msgid "upscale images?" msgstr "¿Aumentar imágenes?" -#: photologue/models.py:581 +#: photologue/models.py:600 msgid "" "If selected the image will be scaled up if necessary to fit the supplied " "dimensions. Cropped sizes will be upscaled regardless of this setting." @@ -249,11 +269,11 @@ msgstr "" "las dimensiones proporcionadas. Los tamaños recortados serán aumentados de " "acuerdo a esta opción." -#: photologue/models.py:585 +#: photologue/models.py:604 msgid "crop to fit?" msgstr "¿Recortar hasta ajustar?" -#: photologue/models.py:587 +#: photologue/models.py:606 msgid "" "If selected the image will be scaled and cropped to fit the supplied " "dimensions." @@ -261,21 +281,21 @@ msgstr "" "Si se selecciona la imagen será escalada y recortada para ajustarse a las " "dimensiones proporcionadas." -#: photologue/models.py:589 +#: photologue/models.py:608 msgid "pre-cache?" msgstr "¿pre-cachear?" -#: photologue/models.py:591 +#: photologue/models.py:610 msgid "If selected this photo size will be pre-cached as photos are added." msgstr "" "Si se selecciona, este tamaño de foto será pre-cacheado cuando se añadan " "nuevas fotos." -#: photologue/models.py:592 +#: photologue/models.py:611 msgid "increment view count?" msgstr "¿incrementar contador de visualizaciones?" -#: photologue/models.py:594 +#: photologue/models.py:613 msgid "" "If selected the image's \"view_count\" will be incremented when this photo " "size is displayed." @@ -283,31 +303,31 @@ msgstr "" "Si se selecciona el \"contador de visualizaciones\" se incrementará cuando " "esta foto sea visualizada." -#: photologue/models.py:599 +#: photologue/models.py:618 msgid "photo size" msgstr "tamaño de foto" -#: photologue/models.py:600 +#: photologue/models.py:619 msgid "photo sizes" msgstr "tamaños de foto" -#: photologue/models.py:617 +#: photologue/models.py:636 msgid "Can only crop photos if both width and height dimensions are set." msgstr "Solo puede recortar las fotos si ancho y alto están establecidos." -#: photologue_custom/admin.py:43 photologue_custom/models.py:51 -msgid "owner" +#: photologue/models.py:702 +msgid "tag" msgstr "" -#: photologue_custom/forms.py:34 +#: photologue_custom/forms.py:22 msgid "Gallery" msgstr "GalerÃa" -#: photologue_custom/forms.py:36 +#: photologue_custom/forms.py:24 msgid "-- Create a new gallery --" msgstr "" -#: photologue_custom/forms.py:37 +#: photologue_custom/forms.py:25 msgid "" "Select a gallery to add these images to. Leave this empty to create a new " "gallery from the supplied title." @@ -315,58 +335,42 @@ msgstr "" "Seleccione una galerÃa para agregarle estas imágenes. Déjelo vacÃo para " "crear una nueva galerÃa a partir de este tÃtulo." -#: photologue_custom/forms.py:41 -#, fuzzy -#| msgid "View all galleries" +#: photologue_custom/forms.py:29 msgid "New gallery title" -msgstr "Ver todas las galerÃas" +msgstr "" -#: photologue_custom/forms.py:46 +#: photologue_custom/forms.py:34 msgid "New gallery event start date" msgstr "" -#: photologue_custom/forms.py:51 +#: photologue_custom/forms.py:39 msgid "New gallery event end date" msgstr "" -#: photologue_custom/forms.py:57 -#, fuzzy -#| msgid "gallery" +#: photologue_custom/forms.py:45 msgid "New gallery tags" -msgstr "galerÃa" +msgstr "" -#: photologue_custom/forms.py:59 +#: photologue_custom/forms.py:47 msgid "" "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." msgstr "" -#: photologue_custom/forms.py:76 +#: photologue_custom/forms.py:64 #: photologue_custom/templates/photologue/upload.html:6 #: photologue_custom/templates/photologue/upload.html:73 msgid "Upload" msgstr "Subir" -#: photologue_custom/forms.py:82 +#: photologue_custom/forms.py:70 msgid "A gallery with that title already exists." msgstr "Ya existe una galerÃa con ese tÃtulo." -#: photologue_custom/forms.py:91 +#: photologue_custom/forms.py:79 msgid "Select an existing gallery, or enter a title for a new gallery." msgstr "" "Seleccione una galerÃa existente o ingrese un nuevo nombre para la galerÃa." -#: photologue_custom/models.py:23 -msgid "start date" -msgstr "" - -#: photologue_custom/models.py:28 -msgid "end date" -msgstr "" - -#: photologue_custom/models.py:56 -msgid "license" -msgstr "" - #: photologue_custom/templates/photologue/gallery_archive.html:7 #: photologue_custom/templates/photologue/gallery_archive.html:12 msgid "Latest photo galleries" @@ -399,16 +403,12 @@ msgid "to" msgstr "" #: photologue_custom/templates/photologue/gallery_detail.html:57 -#, fuzzy -#| msgid "All photos" msgid "All pictures" -msgstr "Todas las fotos" +msgstr "" #: photologue_custom/templates/photologue/gallery_detail.html:78 -#, fuzzy -#| msgid "View all galleries" msgid "Download all gallery" -msgstr "Ver todas las galerÃas" +msgstr "" #: photologue_custom/templates/photologue/photo_detail.html:13 msgid "Published" diff --git a/photologue/locale/fr/LC_MESSAGES/django.po b/photologue/locale/fr/LC_MESSAGES/django.po index f3b69fc..a996627 100644 --- a/photologue/locale/fr/LC_MESSAGES/django.po +++ b/photologue/locale/fr/LC_MESSAGES/django.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: Photologue\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-01-30 07:09+0000\n" +"POT-Creation-Date: 2022-01-30 10:06+0000\n" "PO-Revision-Date: 2017-12-03 14:47+0000\n" "Last-Translator: Richard Barran <richard@arbee-design.co.uk>\n" "Language-Team: French (http://www.transifex.com/richardbarran/django-" @@ -21,75 +21,131 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: photologue/models.py:86 +#: photologue/admin.py:30 photologue/models.py:499 +msgid "owner" +msgstr "propriétaire" + +#: photologue/forms.py:23 +msgid "Gallery" +msgstr "Galerie" + +#: photologue/forms.py:25 +msgid "-- Create a new gallery --" +msgstr "-- Créer une nouvelle galerie --" + +#: photologue/forms.py:26 +msgid "" +"Select a gallery to add these images to. Leave this empty to create a new " +"gallery from the supplied title." +msgstr "" +"Sélectionner une galerie à laquelle ajouter ces images. Laisser ce champ " +"vide pour créer une nouvelle galerie à partir du titre indiqué." + +#: photologue/forms.py:30 +msgid "New gallery title" +msgstr "Titre de la nouvelle galerie" + +#: photologue/forms.py:35 +msgid "New gallery event start date" +msgstr "Date de début de l'évènement de la nouvelle galerie" + +#: photologue/forms.py:40 +msgid "New gallery event end date" +msgstr "Date de fin de l'évènement de la nouvelle galerie" + +#: photologue/forms.py:46 +msgid "New gallery tags" +msgstr "Balises de la nouvelle galerie" + +#: photologue/forms.py:48 +msgid "" +"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgstr "" + +#: photologue/forms.py:65 photologue/templates/photologue/upload.html:6 +#: photologue/templates/photologue/upload.html:73 +msgid "Upload" +msgstr "Télécharger" + +#: photologue/forms.py:71 +msgid "A gallery with that title already exists." +msgstr "Une galerie portant ce nom existe déjà ." + +#: photologue/forms.py:80 +msgid "Select an existing gallery, or enter a title for a new gallery." +msgstr "" +"Sélectionner une galerie existante ou entrer un titre pour une nouvelle " +"galerie." + +#: photologue/models.py:84 msgid "Very Low" msgstr "Très Bas" -#: photologue/models.py:87 +#: photologue/models.py:85 msgid "Low" msgstr "Bas" -#: photologue/models.py:88 +#: photologue/models.py:86 msgid "Medium-Low" msgstr "Moyen-Bas" -#: photologue/models.py:89 +#: photologue/models.py:87 msgid "Medium" msgstr "Moyen" -#: photologue/models.py:90 +#: photologue/models.py:88 msgid "Medium-High" msgstr "Moyen-Haut" -#: photologue/models.py:91 +#: photologue/models.py:89 msgid "High" msgstr "Haut" -#: photologue/models.py:92 +#: photologue/models.py:90 msgid "Very High" msgstr "Très Haut" -#: photologue/models.py:97 +#: photologue/models.py:95 msgid "Top" msgstr "Sommet" -#: photologue/models.py:98 +#: photologue/models.py:96 msgid "Right" msgstr "Droite" -#: photologue/models.py:99 +#: photologue/models.py:97 msgid "Bottom" msgstr "Bas" -#: photologue/models.py:100 +#: photologue/models.py:98 msgid "Left" msgstr "Gauche" -#: photologue/models.py:101 +#: photologue/models.py:99 msgid "Center (Default)" msgstr "Centré (par défaut)" -#: photologue/models.py:105 +#: photologue/models.py:103 msgid "Flip left to right" msgstr "Inversion de gauche à droite" -#: photologue/models.py:106 +#: photologue/models.py:104 msgid "Flip top to bottom" msgstr "Inversion de haut en bas" -#: photologue/models.py:107 +#: photologue/models.py:105 msgid "Rotate 90 degrees counter-clockwise" msgstr "Rotation de 90 degrés dans le sens anti-horloger" -#: photologue/models.py:108 +#: photologue/models.py:106 msgid "Rotate 90 degrees clockwise" msgstr "Rotation de 90 degrés dans le sens horloger" -#: photologue/models.py:109 +#: photologue/models.py:107 msgid "Rotate 180 degrees" msgstr "Rotation de 180 degrés" -#: photologue/models.py:119 +#: photologue/models.py:117 #, python-format msgid "" "Chain multiple filters using the following pattern \"FILTER_ONE->FILTER_TWO-" @@ -100,107 +156,123 @@ msgstr "" ">FILTRE_DEUX->FILTRE_TROIS\". Les filtres d'image seront appliqués dans " "l'ordre. Les filtres suivants sont disponibles: %s." -#: photologue/models.py:141 +#: photologue/models.py:139 msgid "date published" msgstr "date de publication" -#: photologue/models.py:143 photologue/models.py:474 +#: photologue/models.py:141 photologue/models.py:485 msgid "title" msgstr "titre" -#: photologue/models.py:146 +#: photologue/models.py:144 msgid "title slug" msgstr "version abrégée du titre" -#: photologue/models.py:149 photologue/models.py:480 +#: photologue/models.py:147 photologue/models.py:491 photologue/models.py:697 msgid "A \"slug\" is a unique URL-friendly title for an object." msgstr "" "Un \"slug\" est un titre abrégé et unique, compatible avec les URL, pour un " "objet." #: photologue/models.py:150 +msgid "start date" +msgstr "date de début" + +#: photologue/models.py:155 +msgid "end date" +msgstr "date de fin" + +#: photologue/models.py:157 msgid "description" msgstr "description" -#: photologue/models.py:152 photologue/models.py:485 +#: photologue/models.py:162 photologue/models.py:703 +msgid "tags" +msgstr "balises" + +#: photologue/models.py:165 photologue/models.py:506 msgid "is public" msgstr "est public" -#: photologue/models.py:154 +#: photologue/models.py:167 msgid "Public galleries will be displayed in the default views." msgstr "Les galeries publiques seront affichée dans les vues par défaut." -#: photologue/models.py:158 photologue/models.py:495 +#: photologue/models.py:171 photologue/models.py:514 msgid "photos" msgstr "photos" -#: photologue/models.py:166 +#: photologue/models.py:177 msgid "gallery" msgstr "galerie" -#: photologue/models.py:167 +#: photologue/models.py:178 msgid "galleries" msgstr "galleries" -#: photologue/models.py:202 +#: photologue/models.py:213 msgid "count" msgstr "nombre" -#: photologue/models.py:210 +#: photologue/models.py:221 msgid "image" msgstr "image" -#: photologue/models.py:213 +#: photologue/models.py:224 msgid "date taken" msgstr "date de prise de vue" -#: photologue/models.py:216 +#: photologue/models.py:227 msgid "Date image was taken; is obtained from the image EXIF data." msgstr "" "La date à laquelle l'image a été prise ; obtenue à partir des données EXIF " "de l'image." -#: photologue/models.py:217 +#: photologue/models.py:228 msgid "view count" msgstr "nombre" -#: photologue/models.py:220 +#: photologue/models.py:231 msgid "crop from" msgstr "découper à partir de" -#: photologue/models.py:243 +#: photologue/models.py:254 msgid "An \"admin_thumbnail\" photo size has not been defined." msgstr "Une taille de photo \"admin_thumbnail\" n'a pas encore été définie." -#: photologue/models.py:250 +#: photologue/models.py:261 msgid "Thumbnail" msgstr "Miniature" -#: photologue/models.py:477 +#: photologue/models.py:488 photologue/models.py:696 msgid "slug" msgstr "libellé court" -#: photologue/models.py:481 +#: photologue/models.py:492 msgid "caption" msgstr "légende" -#: photologue/models.py:483 +#: photologue/models.py:494 msgid "date added" msgstr "date d'ajout" -#: photologue/models.py:487 +#: photologue/models.py:504 +msgid "license" +msgstr "licence" + +#: photologue/models.py:508 msgid "Public photographs will be displayed in the default views." msgstr "Les photographies publique seront affichées dans les vues par défaut." -#: photologue/models.py:494 +#: photologue/models.py:513 msgid "photo" msgstr "photo" -#: photologue/models.py:556 +#: photologue/models.py:575 photologue/models.py:691 msgid "name" msgstr "nom" -#: photologue/models.py:560 +#: photologue/models.py:579 msgid "" "Photo size name should contain only letters, numbers and underscores. " "Examples: \"thumbnail\", \"display\", \"small\", \"main_page_widget\"." @@ -209,41 +281,41 @@ msgstr "" "chiffres et des caractères de soulignement. Exemples: \"miniature\", " "\"affichage\", \"petit\", \"widget_page_principale\"." -#: photologue/models.py:567 +#: photologue/models.py:586 msgid "width" msgstr "largeur" -#: photologue/models.py:570 +#: photologue/models.py:589 msgid "" "If width is set to \"0\" the image will be scaled to the supplied height." msgstr "" "Si la largeur est réglée à \"0\" l l'image sera redimensionnée par rapport à " "la hauteur fournie." -#: photologue/models.py:571 +#: photologue/models.py:590 msgid "height" msgstr "hauteur" -#: photologue/models.py:574 +#: photologue/models.py:593 msgid "" "If height is set to \"0\" the image will be scaled to the supplied width" msgstr "" "Si la hauteur est réglée à \"0\" l l'image sera redimensionnée par rapport à " "la largeur fournie." -#: photologue/models.py:575 +#: photologue/models.py:594 msgid "quality" msgstr "qualité" -#: photologue/models.py:578 +#: photologue/models.py:597 msgid "JPEG image quality." msgstr "Qualité JPEG de l'image." -#: photologue/models.py:579 +#: photologue/models.py:598 msgid "upscale images?" msgstr "agrandir les images ?" -#: photologue/models.py:581 +#: photologue/models.py:600 msgid "" "If selected the image will be scaled up if necessary to fit the supplied " "dimensions. Cropped sizes will be upscaled regardless of this setting." @@ -252,11 +324,11 @@ msgstr "" "dimensions fournies. Les dimensions ajustées seront agrandies sans prendre " "en compte ce paramètre." -#: photologue/models.py:585 +#: photologue/models.py:604 msgid "crop to fit?" msgstr "découper pour adapter à la taille ?" -#: photologue/models.py:587 +#: photologue/models.py:606 msgid "" "If selected the image will be scaled and cropped to fit the supplied " "dimensions." @@ -264,21 +336,21 @@ msgstr "" "Si sélectionné l'image sera redimensionnée et recadrée pour coïncider avec " "les dimensions fournies." -#: photologue/models.py:589 +#: photologue/models.py:608 msgid "pre-cache?" msgstr "mise en cache ?" -#: photologue/models.py:591 +#: photologue/models.py:610 msgid "If selected this photo size will be pre-cached as photos are added." msgstr "" "Si sélectionné cette taille de photo sera mise en cache au moment au les " "photos sont ajoutées." -#: photologue/models.py:592 +#: photologue/models.py:611 msgid "increment view count?" msgstr "incrémenter le nombre d'affichages ?" -#: photologue/models.py:594 +#: photologue/models.py:613 msgid "" "If selected the image's \"view_count\" will be incremented when this photo " "size is displayed." @@ -286,148 +358,75 @@ msgstr "" "Si sélectionné le \"view_count\" (nombre d'affichage) de l'image sera " "incrémenté quand cette taille de photo sera affichée." -#: photologue/models.py:599 +#: photologue/models.py:618 msgid "photo size" msgstr "taille de la photo" -#: photologue/models.py:600 +#: photologue/models.py:619 msgid "photo sizes" msgstr "tailles des photos" -#: photologue/models.py:617 +#: photologue/models.py:636 msgid "Can only crop photos if both width and height dimensions are set." msgstr "" "La hauteur et la largeur doivent être toutes les deux définies pour " "retailler des photos." -#: photologue_custom/admin.py:43 photologue_custom/models.py:51 -msgid "owner" -msgstr "" - -#: photologue_custom/forms.py:34 -msgid "Gallery" -msgstr "Galerie" - -#: photologue_custom/forms.py:36 -msgid "-- Create a new gallery --" -msgstr "" - -#: photologue_custom/forms.py:37 -msgid "" -"Select a gallery to add these images to. Leave this empty to create a new " -"gallery from the supplied title." -msgstr "" -"Sélectionner une galerie à laquelle ajouter ces images. Laisser ce champ " -"vide pour créer une nouvelle galerie à partir du titre indiqué." - -#: photologue_custom/forms.py:41 -#, fuzzy -#| msgid "View all galleries" -msgid "New gallery title" -msgstr "Afficher toutes les galeries" - -#: photologue_custom/forms.py:46 -msgid "New gallery event start date" -msgstr "" - -#: photologue_custom/forms.py:51 -msgid "New gallery event end date" -msgstr "" - -#: photologue_custom/forms.py:57 -#, fuzzy -#| msgid "gallery uploads" -msgid "New gallery tags" -msgstr "gallery uploads" - -#: photologue_custom/forms.py:59 -msgid "" -"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +#: photologue/models.py:702 +msgid "tag" msgstr "" -#: photologue_custom/forms.py:76 -#: photologue_custom/templates/photologue/upload.html:6 -#: photologue_custom/templates/photologue/upload.html:73 -msgid "Upload" -msgstr "Télécharger" - -#: photologue_custom/forms.py:82 -msgid "A gallery with that title already exists." -msgstr "Une galerie portant ce nom existe déjà ." - -#: photologue_custom/forms.py:91 -msgid "Select an existing gallery, or enter a title for a new gallery." -msgstr "" -"Sélectionner une galerie existante ou entrer un titre pour une nouvelle " -"galerie." - -#: photologue_custom/models.py:23 -msgid "start date" -msgstr "" - -#: photologue_custom/models.py:28 -msgid "end date" -msgstr "" - -#: photologue_custom/models.py:56 -msgid "license" -msgstr "" - -#: photologue_custom/templates/photologue/gallery_archive.html:7 -#: photologue_custom/templates/photologue/gallery_archive.html:12 +#: photologue/templates/photologue/gallery_archive.html:7 +#: photologue/templates/photologue/gallery_archive.html:12 msgid "Latest photo galleries" msgstr "Dernières galeries de photos" -#: photologue_custom/templates/photologue/gallery_archive.html:18 +#: photologue/templates/photologue/gallery_archive.html:18 msgid "Filter by year" msgstr "Filtrer par année" -#: photologue_custom/templates/photologue/gallery_archive.html:35 +#: photologue/templates/photologue/gallery_archive.html:35 msgid "No galleries were found" msgstr "Aucune galerie trouvée" -#: photologue_custom/templates/photologue/gallery_archive_year.html:7 -#: photologue_custom/templates/photologue/gallery_archive_year.html:12 +#: photologue/templates/photologue/gallery_archive_year.html:7 +#: photologue/templates/photologue/gallery_archive_year.html:12 #, python-format msgid "Galleries for %(show_year)s" msgstr "Galeries de %(show_year)s" -#: photologue_custom/templates/photologue/gallery_archive_year.html:17 +#: photologue/templates/photologue/gallery_archive_year.html:17 msgid "View all galleries" msgstr "Afficher toutes les galeries" -#: photologue_custom/templates/photologue/gallery_archive_year.html:29 +#: photologue/templates/photologue/gallery_archive_year.html:29 msgid "No galleries were found." msgstr "Aucune galerie trouvée." -#: photologue_custom/templates/photologue/gallery_detail.html:41 +#: photologue/templates/photologue/gallery_detail.html:41 msgid "to" -msgstr "" +msgstr "au" -#: photologue_custom/templates/photologue/gallery_detail.html:57 -#, fuzzy -#| msgid "All photos" +#: photologue/templates/photologue/gallery_detail.html:57 msgid "All pictures" msgstr "Toutes les photos" -#: photologue_custom/templates/photologue/gallery_detail.html:78 -#, fuzzy -#| msgid "View all galleries" +#: photologue/templates/photologue/gallery_detail.html:78 msgid "Download all gallery" -msgstr "Afficher toutes les galeries" +msgstr "Télécharger toute la galerie" -#: photologue_custom/templates/photologue/photo_detail.html:13 +#: photologue/templates/photologue/photo_detail.html:13 msgid "Published" msgstr "Publiée le" -#: photologue_custom/templates/photologue/photo_detail.html:25 +#: photologue/templates/photologue/photo_detail.html:25 msgid "This photo is found in the following galleries" msgstr "Cette photo se trouve dans les galeries suivantes" -#: photologue_custom/templates/photologue/upload.html:78 +#: photologue/templates/photologue/upload.html:78 msgid "Drag and drop photos here" -msgstr "" +msgstr "Glissez et déposez les photos ici" -#: photologue_custom/templates/photologue/upload.html:82 +#: photologue/templates/photologue/upload.html:82 msgid "Owner will be" -msgstr "" +msgstr "Le propriétaire sera" diff --git a/photologue_custom/management/commands/duplicate.py b/photologue/management/commands/duplicate.py similarity index 100% rename from photologue_custom/management/commands/duplicate.py rename to photologue/management/commands/duplicate.py index 97a902a..56ce185 100644 --- a/photologue_custom/management/commands/duplicate.py +++ b/photologue/management/commands/duplicate.py @@ -1,8 +1,8 @@ +import hashlib + from django.core.management.base import BaseCommand, CommandError from photologue.models import Gallery -import hashlib - class Command(BaseCommand): help = 'List all duplicate for chosen galleries' diff --git a/photologue_custom/management/commands/rename_media.py b/photologue/management/commands/rename_media.py similarity index 100% rename from photologue_custom/management/commands/rename_media.py rename to photologue/management/commands/rename_media.py index 461870b..1f8767e 100644 --- a/photologue_custom/management/commands/rename_media.py +++ b/photologue/management/commands/rename_media.py @@ -1,9 +1,9 @@ -from pathlib import Path import os +from pathlib import Path +from django.conf import settings from django.core.management.base import BaseCommand from photologue.models import Gallery -from django.conf import settings class Command(BaseCommand): diff --git a/photologue/migrations/0014_merge_related.py b/photologue/migrations/0014_merge_related.py index 2608233..8dfa458 100644 --- a/photologue/migrations/0014_merge_related.py +++ b/photologue/migrations/0014_merge_related.py @@ -1,12 +1,12 @@ # Generated by Django 3.2.11 on 2022-01-30 08:32 -from django.conf import settings -from django.db import migrations, models import django.db.models.deletion import django.utils.timezone import taggit.managers +from django.conf import settings from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType +from django.db import migrations, models from django.template.defaultfilters import slugify numens = User.objects.get(username="Numens").id diff --git a/photologue_custom/static/lightgallery/css/lg-thumbnail.css b/photologue/static/lightgallery/css/lg-thumbnail.css similarity index 100% rename from photologue_custom/static/lightgallery/css/lg-thumbnail.css rename to photologue/static/lightgallery/css/lg-thumbnail.css diff --git a/photologue_custom/static/lightgallery/css/lg-zoom.css b/photologue/static/lightgallery/css/lg-zoom.css similarity index 100% rename from photologue_custom/static/lightgallery/css/lg-zoom.css rename to photologue/static/lightgallery/css/lg-zoom.css diff --git a/photologue_custom/static/lightgallery/css/lightgallery.css b/photologue/static/lightgallery/css/lightgallery.css similarity index 100% rename from photologue_custom/static/lightgallery/css/lightgallery.css rename to photologue/static/lightgallery/css/lightgallery.css diff --git a/photologue_custom/static/lightgallery/fonts/lg.svg b/photologue/static/lightgallery/fonts/lg.svg similarity index 100% rename from photologue_custom/static/lightgallery/fonts/lg.svg rename to photologue/static/lightgallery/fonts/lg.svg diff --git a/photologue_custom/static/lightgallery/fonts/lg.ttf b/photologue/static/lightgallery/fonts/lg.ttf similarity index 100% rename from photologue_custom/static/lightgallery/fonts/lg.ttf rename to photologue/static/lightgallery/fonts/lg.ttf diff --git a/photologue_custom/static/lightgallery/fonts/lg.woff b/photologue/static/lightgallery/fonts/lg.woff similarity index 100% rename from photologue_custom/static/lightgallery/fonts/lg.woff rename to photologue/static/lightgallery/fonts/lg.woff diff --git a/photologue_custom/static/lightgallery/fonts/lg.woff2 b/photologue/static/lightgallery/fonts/lg.woff2 similarity index 100% rename from photologue_custom/static/lightgallery/fonts/lg.woff2 rename to photologue/static/lightgallery/fonts/lg.woff2 diff --git a/photologue_custom/static/lightgallery/images/loading.gif b/photologue/static/lightgallery/images/loading.gif similarity index 100% rename from photologue_custom/static/lightgallery/images/loading.gif rename to photologue/static/lightgallery/images/loading.gif diff --git a/photologue_custom/static/lightgallery/lightgallery.min.js b/photologue/static/lightgallery/lightgallery.min.js similarity index 100% rename from photologue_custom/static/lightgallery/lightgallery.min.js rename to photologue/static/lightgallery/lightgallery.min.js diff --git a/photologue_custom/static/lightgallery/plugins/admin/lg-admin.js b/photologue/static/lightgallery/plugins/admin/lg-admin.js similarity index 100% rename from photologue_custom/static/lightgallery/plugins/admin/lg-admin.js rename to photologue/static/lightgallery/plugins/admin/lg-admin.js diff --git a/photologue_custom/static/lightgallery/plugins/hash/lg-hash.min.js b/photologue/static/lightgallery/plugins/hash/lg-hash.min.js similarity index 100% rename from photologue_custom/static/lightgallery/plugins/hash/lg-hash.min.js rename to photologue/static/lightgallery/plugins/hash/lg-hash.min.js diff --git a/photologue_custom/static/lightgallery/plugins/thumbnail/lg-thumbnail.min.js b/photologue/static/lightgallery/plugins/thumbnail/lg-thumbnail.min.js similarity index 100% rename from photologue_custom/static/lightgallery/plugins/thumbnail/lg-thumbnail.min.js rename to photologue/static/lightgallery/plugins/thumbnail/lg-thumbnail.min.js diff --git a/photologue_custom/static/lightgallery/plugins/zoom/lg-zoom.min.js b/photologue/static/lightgallery/plugins/zoom/lg-zoom.min.js similarity index 100% rename from photologue_custom/static/lightgallery/plugins/zoom/lg-zoom.min.js rename to photologue/static/lightgallery/plugins/zoom/lg-zoom.min.js diff --git a/photologue_custom/templates/admin/photologue/photo/change_list.html b/photologue/templates/admin/photologue/photo/change_list.html similarity index 100% rename from photologue_custom/templates/admin/photologue/photo/change_list.html rename to photologue/templates/admin/photologue/photo/change_list.html diff --git a/photologue_custom/templates/photologue/gallery_archive.html b/photologue/templates/photologue/gallery_archive.html similarity index 100% rename from photologue_custom/templates/photologue/gallery_archive.html rename to photologue/templates/photologue/gallery_archive.html diff --git a/photologue_custom/templates/photologue/gallery_archive_year.html b/photologue/templates/photologue/gallery_archive_year.html similarity index 100% rename from photologue_custom/templates/photologue/gallery_archive_year.html rename to photologue/templates/photologue/gallery_archive_year.html diff --git a/photologue_custom/templates/photologue/gallery_detail.html b/photologue/templates/photologue/gallery_detail.html similarity index 100% rename from photologue_custom/templates/photologue/gallery_detail.html rename to photologue/templates/photologue/gallery_detail.html diff --git a/photologue_custom/templates/photologue/includes/gallery_sample.html b/photologue/templates/photologue/includes/gallery_sample.html similarity index 100% rename from photologue_custom/templates/photologue/includes/gallery_sample.html rename to photologue/templates/photologue/includes/gallery_sample.html diff --git a/photologue_custom/templates/photologue/photo_detail.html b/photologue/templates/photologue/photo_detail.html similarity index 100% rename from photologue_custom/templates/photologue/photo_detail.html rename to photologue/templates/photologue/photo_detail.html diff --git a/photologue_custom/templates/photologue/tag_detail.html b/photologue/templates/photologue/tag_detail.html similarity index 100% rename from photologue_custom/templates/photologue/tag_detail.html rename to photologue/templates/photologue/tag_detail.html diff --git a/photologue_custom/templates/photologue/upload.html b/photologue/templates/photologue/upload.html similarity index 100% rename from photologue_custom/templates/photologue/upload.html rename to photologue/templates/photologue/upload.html diff --git a/photologue/urls.py b/photologue/urls.py index 4772067..e4949f8 100644 --- a/photologue/urls.py +++ b/photologue/urls.py @@ -1,7 +1,8 @@ from django.urls import path, re_path -from photologue_custom.views import CustomGalleryDetailView, GalleryDownload, GalleryUpload, TagDetail -from .views import GalleryArchiveIndexView, GalleryYearArchiveView, PhotoDetailView +from .views import (CustomGalleryDetailView, GalleryArchiveIndexView, + GalleryDownload, GalleryUpload, GalleryYearArchiveView, + PhotoDetailView, TagDetail) app_name = 'photologue' urlpatterns = [ diff --git a/photologue/views.py b/photologue/views.py index 2741b50..77953a8 100644 --- a/photologue/views.py +++ b/photologue/views.py @@ -1,8 +1,26 @@ -from django.contrib.auth.mixins import LoginRequiredMixin +# Copyright (C) 2021 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +import os +import zipfile +from io import BytesIO +from pathlib import Path + +from django.contrib import messages +from django.contrib.auth.mixins import (LoginRequiredMixin, + PermissionRequiredMixin) +from django.core.mail import mail_managers +from django.db import IntegrityError +from django.http import HttpResponse +from django.urls import reverse_lazy +from django.utils.text import slugify from django.views.generic.dates import ArchiveIndexView, YearArchiveView from django.views.generic.detail import DetailView +from django.views.generic.edit import FormView +from PIL import Image -from .models import Gallery, Photo +from .forms import UploadForm +from .models import Gallery, Photo, Tag class GalleryDateView(LoginRequiredMixin): @@ -22,3 +40,125 @@ class GalleryYearArchiveView(GalleryDateView, YearArchiveView): class PhotoDetailView(LoginRequiredMixin, DetailView): queryset = Photo.objects.filter(is_public=True) + + +class TagDetail(LoginRequiredMixin, DetailView): + model = Tag + + def get_context_data(self, **kwargs): + """ + Insert the single object into the context dict. + """ + current_tag = self.get_object().slug + context = super().get_context_data(**kwargs) + context['galleries'] = Gallery.objects.filter(is_public=True) \ + .filter(tags__slug=current_tag) \ + .order_by('-date_start') + return context + + +class CustomGalleryDetailView(LoginRequiredMixin, DetailView): + """ + Custom gallery detail view to filter on photo owner + """ + queryset = Gallery.objects.filter(is_public=True) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + # Query with owner to reduce database lag + context['photos'] = self.object.public().select_related('owner') + + # List owners + context['owners'] = [] + for photo in context['photos']: + if photo.owner not in context['owners']: + context['owners'].append(photo.owner) + + # Filter on owner + if 'owner' in self.kwargs: + context['photos'] = context['photos'].filter(owner__id=self.kwargs['owner']) + + return context + + +class GalleryDownload(LoginRequiredMixin, DetailView): + model = Gallery + + def get(self, request, *args, **kwargs): + """ + Download a zip file of the gallery on GET request. + """ + # Create zip file with pictures + gallery = self.get_object() + byte_data = BytesIO() + zip_file = zipfile.ZipFile(byte_data, "w") + for photo in gallery.public(): + filename = os.path.basename(os.path.normpath(photo.image.path)) + zip_file.write(photo.image.path, filename) + zip_file.close() + + # Return zip file + response = HttpResponse(byte_data.getvalue(), content_type='application/x-zip-compressed') + response['Content-Disposition'] = f"attachment; filename={gallery.slug}.zip" + return response + + +class GalleryUpload(PermissionRequiredMixin, FormView): + """ + Form to upload new photos in a gallery + """ + form_class = UploadForm + template_name = "photologue/upload.html" + success_url = reverse_lazy("photologue:pl-gallery-upload") + permission_required = 'photologue.add_gallery' + + def form_valid(self, form): + # Upload photos + # We take files from the request to support multiple upload + files = self.request.FILES.getlist('file_field') + gallery = form.get_or_create_gallery() + gallery_year = Path(str(gallery.date_start.year)) + gallery_dir = gallery_year / gallery.slug + failed_upload = 0 + for photo_file in files: + # Check that we have a valid image + try: + opened = Image.open(photo_file) + opened.verify() + except Exception: + # Pillow doesn't recognize it as an image, skip it + messages.error(self.request, f"{photo_file.name} was not recognized as an image") + failed_upload += 1 + continue + + title = f"{gallery.title} - {photo_file.name}" + try: + photo = Photo( + title=title, + slug=slugify(title), + owner=self.request.user, + ) + photo_name = str(gallery_dir / photo_file.name) + photo.image.save(photo_name, photo_file) + photo.save() + photo.galleries.set([gallery]) + except IntegrityError: + messages.error(self.request, f"{photo_file.name} was not uploaded. Maybe the photo was already uploaded.") + failed_upload += 1 + + # Notify user then managers + if not failed_upload: + messages.success(self.request, "All photos has been successfully uploaded.") + else: + n_success = len(files) - failed_upload + messages.warning(self.request, f"Only {n_success} photos were successfully uploaded !") + + gallery_title = form.cleaned_data['gallery'] or form.cleaned_data.get('new_gallery_title', '') + photos = ", ".join(f.name for f in files) + mail_managers( + subject="New photos upload", + message=f"{self.request.user.username} has uploaded in `{gallery_title}`: {photos}", + ) + + return super().form_valid(form) diff --git a/photologue_custom/views.py b/photologue_custom/views.py deleted file mode 100644 index 38ebc7f..0000000 --- a/photologue_custom/views.py +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright (C) 2021 by BDE ENS Paris-Saclay -# SPDX-License-Identifier: GPL-3.0-or-later - -import os -import zipfile -from io import BytesIO -from pathlib import Path - -from django.contrib import messages -from django.contrib.auth.mixins import (LoginRequiredMixin, - PermissionRequiredMixin) -from django.core.mail import mail_managers -from django.db import IntegrityError -from django.http import HttpResponse -from django.urls import reverse_lazy -from django.utils.text import slugify -from django.views.generic.detail import DetailView -from django.views.generic.edit import FormView -from photologue.models import Gallery, Photo, Tag -from PIL import Image - -from .forms import UploadForm - - -class TagDetail(LoginRequiredMixin, DetailView): - model = Tag - - def get_context_data(self, **kwargs): - """ - Insert the single object into the context dict. - """ - current_tag = self.get_object().slug - context = super().get_context_data(**kwargs) - context['galleries'] = Gallery.objects.filter(is_public=True) \ - .filter(tags__slug=current_tag) \ - .order_by('-date_start') - return context - - -class CustomGalleryDetailView(LoginRequiredMixin, DetailView): - """ - Custom gallery detail view to filter on photo owner - """ - queryset = Gallery.objects.filter(is_public=True) - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - - # Query with owner to reduce database lag - context['photos'] = self.object.public().select_related('owner') - - # List owners - context['owners'] = [] - for photo in context['photos']: - if photo.owner not in context['owners']: - context['owners'].append(photo.owner) - - # Filter on owner - if 'owner' in self.kwargs: - context['photos'] = context['photos'].filter(owner__id=self.kwargs['owner']) - - return context - - -class GalleryDownload(LoginRequiredMixin, DetailView): - model = Gallery - - def get(self, request, *args, **kwargs): - """ - Download a zip file of the gallery on GET request. - """ - # Create zip file with pictures - gallery = self.get_object() - byte_data = BytesIO() - zip_file = zipfile.ZipFile(byte_data, "w") - for photo in gallery.public(): - filename = os.path.basename(os.path.normpath(photo.image.path)) - zip_file.write(photo.image.path, filename) - zip_file.close() - - # Return zip file - response = HttpResponse(byte_data.getvalue(), content_type='application/x-zip-compressed') - response['Content-Disposition'] = f"attachment; filename={gallery.slug}.zip" - return response - - -class GalleryUpload(PermissionRequiredMixin, FormView): - """ - Form to upload new photos in a gallery - """ - form_class = UploadForm - template_name = "photologue/upload.html" - success_url = reverse_lazy("photologue:pl-gallery-upload") - permission_required = 'photologue.add_gallery' - - def form_valid(self, form): - # Upload photos - # We take files from the request to support multiple upload - files = self.request.FILES.getlist('file_field') - gallery = form.get_or_create_gallery() - gallery_year = Path(str(gallery.date_start.year)) - gallery_dir = gallery_year / gallery.slug - failed_upload = 0 - for photo_file in files: - # Check that we have a valid image - try: - opened = Image.open(photo_file) - opened.verify() - except Exception: - # Pillow doesn't recognize it as an image, skip it - messages.error(self.request, f"{photo_file.name} was not recognized as an image") - failed_upload += 1 - continue - - title = f"{gallery.title} - {photo_file.name}" - try: - photo = Photo( - title=title, - slug=slugify(title), - owner=self.request.user, - ) - photo_name = str(gallery_dir / photo_file.name) - photo.image.save(photo_name, photo_file) - photo.save() - photo.galleries.set([gallery]) - except IntegrityError: - messages.error(self.request, f"{photo_file.name} was not uploaded. Maybe the photo was already uploaded.") - failed_upload += 1 - - # Notify user then managers - if not failed_upload: - messages.success(self.request, "All photos has been successfully uploaded.") - else: - n_success = len(files) - failed_upload - messages.warning(self.request, f"Only {n_success} photos were successfully uploaded !") - - gallery_title = form.cleaned_data['gallery'] or form.cleaned_data.get('new_gallery_title', '') - photos = ", ".join(f.name for f in files) - mail_managers( - subject="New photos upload", - message=f"{self.request.user.username} has uploaded in `{gallery_title}`: {photos}", - ) - - return super().form_valid(form) diff --git a/tox.ini b/tox.ini index f69e975..885d2da 100644 --- a/tox.ini +++ b/tox.ini @@ -12,7 +12,7 @@ deps = -r{toxinidir}/requirements.txt coverage commands = - coverage run --omit='photo21/wsgi.py' --source=photo21,photologue,photologue_custom ./manage.py test + coverage run --omit='photo21/wsgi.py' --source=photo21,photologue ./manage.py test coverage report -m [testenv:linters] @@ -26,7 +26,7 @@ deps = pep8-naming pyflakes commands = - flake8 photo21 photologue photologue_custom + flake8 photo21 photologue [flake8] ignore = W503, I100, I101 -- GitLab From 80085edeeb4eecf44f075176e306bdcf2ab1d4b1 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss <erdnaxe@crans.org> Date: Sun, 30 Jan 2022 11:15:41 +0100 Subject: [PATCH 7/9] Reset migrations --- photo21/settings.py | 3 - photologue/migrations/0001_initial.py | 166 ++++++------------ photologue/migrations/0002_photosize_data.py | 43 ----- .../migrations/0003_auto_20140822_1716.py | 19 -- .../migrations/0004_auto_20140915_1259.py | 35 ---- .../migrations/0005_auto_20141027_1552.py | 20 --- .../migrations/0006_auto_20141028_2005.py | 21 --- .../migrations/0007_auto_20150404_1737.py | 30 ---- .../migrations/0008_auto_20150509_1557.py | 22 --- .../migrations/0009_auto_20160102_0904.py | 20 --- .../migrations/0010_auto_20160105_1307.py | 35 ---- .../migrations/0011_auto_20190223_2138.py | 18 -- .../migrations/0012_auto_20220129_2207.py | 39 ---- .../migrations/0013_alter_gallery_photos.py | 18 -- photologue/migrations/0014_merge_related.py | 96 ---------- photologue_custom/__init__.py | 0 photologue_custom/apps.py | 6 - photologue_custom/migrations/0001_initial.py | 44 ----- .../migrations/0002_auto_20211011_1956.py | 23 --- .../migrations/0003_auto_20211013_1507.py | 24 --- .../migrations/0004_photoextended_license.py | 18 -- .../migrations/0005_auto_20220130_0953.py | 27 --- photologue_custom/migrations/__init__.py | 0 23 files changed, 52 insertions(+), 675 deletions(-) delete mode 100644 photologue/migrations/0002_photosize_data.py delete mode 100644 photologue/migrations/0003_auto_20140822_1716.py delete mode 100644 photologue/migrations/0004_auto_20140915_1259.py delete mode 100644 photologue/migrations/0005_auto_20141027_1552.py delete mode 100644 photologue/migrations/0006_auto_20141028_2005.py delete mode 100644 photologue/migrations/0007_auto_20150404_1737.py delete mode 100644 photologue/migrations/0008_auto_20150509_1557.py delete mode 100644 photologue/migrations/0009_auto_20160102_0904.py delete mode 100644 photologue/migrations/0010_auto_20160105_1307.py delete mode 100644 photologue/migrations/0011_auto_20190223_2138.py delete mode 100644 photologue/migrations/0012_auto_20220129_2207.py delete mode 100644 photologue/migrations/0013_alter_gallery_photos.py delete mode 100644 photologue/migrations/0014_merge_related.py delete mode 100644 photologue_custom/__init__.py delete mode 100644 photologue_custom/apps.py delete mode 100644 photologue_custom/migrations/0001_initial.py delete mode 100644 photologue_custom/migrations/0002_auto_20211011_1956.py delete mode 100644 photologue_custom/migrations/0003_auto_20211013_1507.py delete mode 100644 photologue_custom/migrations/0004_photoextended_license.py delete mode 100644 photologue_custom/migrations/0005_auto_20220130_0953.py delete mode 100644 photologue_custom/migrations/__init__.py diff --git a/photo21/settings.py b/photo21/settings.py index 9b2844b..e6773ec 100644 --- a/photo21/settings.py +++ b/photo21/settings.py @@ -63,7 +63,6 @@ INSTALLED_APPS = [ 'allauth_note_kfet', 'crispy_forms', 'photologue', - 'taggit', ] MIDDLEWARE = [ @@ -155,8 +154,6 @@ USE_L10N = True USE_TZ = True -DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' - # Limit available languages to this subset LANGUAGES = [ ('de', _('German')), diff --git a/photologue/migrations/0001_initial.py b/photologue/migrations/0001_initial.py index 35d3b3d..47bca5b 100644 --- a/photologue/migrations/0001_initial.py +++ b/photologue/migrations/0001_initial.py @@ -1,158 +1,96 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals +# Generated by Django 3.2.11 on 2022-01-30 10:14 +from django.conf import settings import django.core.validators -import django.utils.timezone -import sortedm2m.fields from django.db import migrations, models - +import django.db.models.deletion +import django.utils.timezone import photologue.models class Migration(migrations.Migration): + initial = True + dependencies = [ - ('sites', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( - name='Gallery', + name='PhotoSize', fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)), - ('date_added', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date published')), - ('title', models.CharField(max_length=50, verbose_name='title', unique=True)), - ('slug', models.SlugField(help_text='A "slug" is a unique URL-friendly title for an object.', verbose_name='title slug', unique=True)), - ('description', models.TextField(blank=True, verbose_name='description')), - ('is_public', models.BooleanField(help_text='Public galleries will be displayed in the default views.', verbose_name='is public', default=True)), - ('tags', photologue.models.TagField(max_length=255, help_text='Django-tagging was not found, tags will be treated as plain text.', blank=True, verbose_name='tags')), - ('sites', models.ManyToManyField(blank=True, verbose_name='sites', null=True, to='sites.Site')), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(help_text='Photo size name should contain only letters, numbers and underscores. Examples: "thumbnail", "display", "small", "main_page_widget".', max_length=40, unique=True, validators=[django.core.validators.RegexValidator(message='Use only plain lowercase letters (ASCII), numbers and underscores.', regex='^[a-z0-9_]+$')], verbose_name='name')), + ('width', models.PositiveIntegerField(default=0, help_text='If width is set to "0" the image will be scaled to the supplied height.', verbose_name='width')), + ('height', models.PositiveIntegerField(default=0, help_text='If height is set to "0" the image will be scaled to the supplied width', verbose_name='height')), + ('quality', models.PositiveIntegerField(choices=[(30, 'Very Low'), (40, 'Low'), (50, 'Medium-Low'), (60, 'Medium'), (70, 'Medium-High'), (80, 'High'), (90, 'Very High')], default=70, help_text='JPEG image quality.', verbose_name='quality')), + ('upscale', models.BooleanField(default=False, help_text='If selected the image will be scaled up if necessary to fit the supplied dimensions. Cropped sizes will be upscaled regardless of this setting.', verbose_name='upscale images?')), + ('crop', models.BooleanField(default=False, help_text='If selected the image will be scaled and cropped to fit the supplied dimensions.', verbose_name='crop to fit?')), + ('pre_cache', models.BooleanField(default=False, help_text='If selected this photo size will be pre-cached as photos are added.', verbose_name='pre-cache?')), + ('increment_count', models.BooleanField(default=False, help_text='If selected the image\'s "view_count" will be incremented when this photo size is displayed.', verbose_name='increment view count?')), ], options={ - 'get_latest_by': 'date_added', - 'verbose_name': 'gallery', - 'ordering': ['-date_added'], - 'verbose_name_plural': 'galleries', + 'verbose_name': 'photo size', + 'verbose_name_plural': 'photo sizes', + 'ordering': ['width', 'height'], }, - bases=(models.Model,), ), migrations.CreateModel( - name='GalleryUpload', + name='Tag', fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)), - ('zip_file', models.FileField(help_text='Select a .zip file of images to upload into a new Gallery.', verbose_name='images file (.zip)', upload_to='photologue/temp')), - ('title', models.CharField(max_length=50, help_text='All uploaded photos will be given a title made up of this title + a sequential number.', verbose_name='title')), - ('caption', models.TextField(help_text='Caption will be added to all photos.', blank=True, verbose_name='caption')), - ('description', models.TextField(help_text='A description of this Gallery.', blank=True, verbose_name='description')), - ('is_public', models.BooleanField(help_text='Uncheck this to make the uploaded gallery and included photographs private.', verbose_name='is public', default=True)), - ('tags', models.CharField(max_length=255, help_text='Django-tagging was not found, tags will be treated as plain text.', blank=True, verbose_name='tags')), - ('gallery', models.ForeignKey(blank=True, verbose_name='gallery', null=True, help_text='Select a gallery to add these images to. Leave this empty to create a new gallery from the supplied title.', to='photologue.Gallery', on_delete=models.CASCADE)), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=250, unique=True, verbose_name='name')), + ('slug', models.SlugField(help_text='A "slug" is a unique URL-friendly title for an object.', max_length=250, unique=True, verbose_name='slug')), ], options={ - 'verbose_name': 'gallery upload', - 'verbose_name_plural': 'gallery uploads', + 'verbose_name': 'tag', + 'verbose_name_plural': 'tags', + 'ordering': ['name'], }, - bases=(models.Model,), ), migrations.CreateModel( name='Photo', fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('image', models.ImageField(upload_to=photologue.models.get_storage_path, verbose_name='image')), - ('date_taken', models.DateTimeField(verbose_name='date taken', blank=True, editable=False, null=True)), - ('view_count', models.PositiveIntegerField(verbose_name='view count', default=0, editable=False)), - ('crop_from', models.CharField(max_length=10, default='center', blank=True, verbose_name='crop from', choices=[('top', 'Top'), ('right', 'Right'), ('bottom', 'Bottom'), ('left', 'Left'), ('center', 'Center (Default)')])), - ('title', models.CharField(max_length=50, verbose_name='title', unique=True)), - ('slug', models.SlugField(help_text='A "slug" is a unique URL-friendly title for an object.', verbose_name='slug', unique=True)), + ('date_taken', models.DateTimeField(blank=True, help_text='Date image was taken; is obtained from the image EXIF data.', null=True, verbose_name='date taken')), + ('view_count', models.PositiveIntegerField(default=0, editable=False, verbose_name='view count')), + ('crop_from', models.CharField(blank=True, choices=[('top', 'Top'), ('right', 'Right'), ('bottom', 'Bottom'), ('left', 'Left'), ('center', 'Center (Default)')], default='center', max_length=10, verbose_name='crop from')), + ('title', models.CharField(max_length=250, unique=True, verbose_name='title')), + ('slug', models.SlugField(help_text='A "slug" is a unique URL-friendly title for an object.', max_length=250, unique=True, verbose_name='slug')), ('caption', models.TextField(blank=True, verbose_name='caption')), ('date_added', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date added')), - ('is_public', models.BooleanField(help_text='Public photographs will be displayed in the default views.', verbose_name='is public', default=True)), - ('tags', photologue.models.TagField(max_length=255, help_text='Django-tagging was not found, tags will be treated as plain text.', blank=True, verbose_name='tags')), - ('sites', models.ManyToManyField(blank=True, verbose_name='sites', null=True, to='sites.Site')), + ('license', models.CharField(blank=True, max_length=255, verbose_name='license')), + ('is_public', models.BooleanField(default=True, help_text='Public photographs will be displayed in the default views.', verbose_name='is public')), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='owner')), ], options={ - 'get_latest_by': 'date_added', 'verbose_name': 'photo', - 'ordering': ['-date_added'], 'verbose_name_plural': 'photos', + 'ordering': ['-date_added'], + 'get_latest_by': 'date_added', }, - bases=(models.Model,), - ), - migrations.AddField( - model_name='gallery', - name='photos', - field=sortedm2m.fields.SortedManyToManyField(blank=True, verbose_name='photos', null=True, to='photologue.Photo'), - preserve_default=True, - ), - migrations.CreateModel( - name='PhotoEffect', - fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)), - ('name', models.CharField(max_length=30, verbose_name='name', unique=True)), - ('description', models.TextField(blank=True, verbose_name='description')), - ('transpose_method', models.CharField(max_length=15, blank=True, verbose_name='rotate or flip', choices=[('FLIP_LEFT_RIGHT', 'Flip left to right'), ('FLIP_TOP_BOTTOM', 'Flip top to bottom'), ('ROTATE_90', 'Rotate 90 degrees counter-clockwise'), ('ROTATE_270', 'Rotate 90 degrees clockwise'), ('ROTATE_180', 'Rotate 180 degrees')])), - ('color', models.FloatField(help_text='A factor of 0.0 gives a black and white image, a factor of 1.0 gives the original image.', verbose_name='color', default=1.0)), - ('brightness', models.FloatField(help_text='A factor of 0.0 gives a black image, a factor of 1.0 gives the original image.', verbose_name='brightness', default=1.0)), - ('contrast', models.FloatField(help_text='A factor of 0.0 gives a solid grey image, a factor of 1.0 gives the original image.', verbose_name='contrast', default=1.0)), - ('sharpness', models.FloatField(help_text='A factor of 0.0 gives a blurred image, a factor of 1.0 gives the original image.', verbose_name='sharpness', default=1.0)), - ('filters', models.CharField(max_length=200, help_text='Chain multiple filters using the following pattern "FILTER_ONE->FILTER_TWO->FILTER_THREE". Image filters will be applied in order. The following filters are available: BLUR, CONTOUR, DETAIL, EDGE_ENHANCE, EDGE_ENHANCE_MORE, EMBOSS, FIND_EDGES, SHARPEN, SMOOTH, SMOOTH_MORE.', blank=True, verbose_name='filters')), - ('reflection_size', models.FloatField(help_text='The height of the reflection as a percentage of the orignal image. A factor of 0.0 adds no reflection, a factor of 1.0 adds a reflection equal to the height of the orignal image.', verbose_name='size', default=0)), - ('reflection_strength', models.FloatField(help_text='The initial opacity of the reflection gradient.', verbose_name='strength', default=0.6)), - ('background_color', models.CharField(max_length=7, help_text='The background color of the reflection gradient. Set this to match the background color of your page.', verbose_name='color', default='#FFFFFF')), - ], - options={ - 'verbose_name': 'photo effect', - 'verbose_name_plural': 'photo effects', - }, - bases=(models.Model,), - ), - migrations.AddField( - model_name='photo', - name='effect', - field=models.ForeignKey(blank=True, verbose_name='effect', null=True, to='photologue.PhotoEffect', on_delete=models.CASCADE), - preserve_default=True, - ), - migrations.CreateModel( - name='PhotoSize', - fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)), - ('name', models.CharField(max_length=40, help_text='Photo size name should contain only letters, numbers and underscores. Examples: "thumbnail", "display", "small", "main_page_widget".', verbose_name='name', unique=True, validators=[django.core.validators.RegexValidator(regex='^[a-z0-9_]+$', message='Use only plain lowercase letters (ASCII), numbers and underscores.')])), - ('width', models.PositiveIntegerField(help_text='If width is set to "0" the image will be scaled to the supplied height.', verbose_name='width', default=0)), - ('height', models.PositiveIntegerField(help_text='If height is set to "0" the image will be scaled to the supplied width', verbose_name='height', default=0)), - ('quality', models.PositiveIntegerField(help_text='JPEG image quality.', verbose_name='quality', choices=[(30, 'Very Low'), (40, 'Low'), (50, 'Medium-Low'), (60, 'Medium'), (70, 'Medium-High'), (80, 'High'), (90, 'Very High')], default=70)), - ('upscale', models.BooleanField(help_text='If selected the image will be scaled up if necessary to fit the supplied dimensions. Cropped sizes will be upscaled regardless of this setting.', verbose_name='upscale images?', default=False)), - ('crop', models.BooleanField(help_text='If selected the image will be scaled and cropped to fit the supplied dimensions.', verbose_name='crop to fit?', default=False)), - ('pre_cache', models.BooleanField(help_text='If selected this photo size will be pre-cached as photos are added.', verbose_name='pre-cache?', default=False)), - ('increment_count', models.BooleanField(help_text='If selected the image\'s "view_count" will be incremented when this photo size is displayed.', verbose_name='increment view count?', default=False)), - ('effect', models.ForeignKey(blank=True, verbose_name='photo effect', null=True, to='photologue.PhotoEffect', on_delete=models.CASCADE)), - ], - options={ - 'verbose_name': 'photo size', - 'ordering': ['width', 'height'], - 'verbose_name_plural': 'photo sizes', - }, - bases=(models.Model,), ), migrations.CreateModel( - name='Watermark', + name='Gallery', fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)), - ('name', models.CharField(max_length=30, verbose_name='name', unique=True)), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date_added', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date published')), + ('title', models.CharField(max_length=250, unique=True, verbose_name='title')), + ('slug', models.SlugField(help_text='A "slug" is a unique URL-friendly title for an object.', max_length=250, unique=True, verbose_name='title slug')), + ('date_start', models.DateField(default=django.utils.timezone.now, verbose_name='start date')), + ('date_end', models.DateField(blank=True, null=True, verbose_name='end date')), ('description', models.TextField(blank=True, verbose_name='description')), - ('image', models.ImageField(upload_to='photologue/watermarks', verbose_name='image')), - ('style', models.CharField(max_length=5, default='scale', verbose_name='style', choices=[('tile', 'Tile'), ('scale', 'Scale')])), - ('opacity', models.FloatField(help_text='The opacity of the overlay.', verbose_name='opacity', default=1)), + ('is_public', models.BooleanField(default=True, help_text='Public galleries will be displayed in the default views.', verbose_name='is public')), + ('photos', models.ManyToManyField(blank=True, related_name='galleries', to='photologue.Photo', verbose_name='photos')), + ('tags', models.ManyToManyField(blank=True, related_name='galleries', to='photologue.Tag', verbose_name='tags')), ], options={ - 'verbose_name': 'watermark', - 'verbose_name_plural': 'watermarks', + 'verbose_name': 'gallery', + 'verbose_name_plural': 'galleries', + 'ordering': ['-date_added'], + 'get_latest_by': 'date_added', }, - bases=(models.Model,), - ), - migrations.AddField( - model_name='photosize', - name='watermark', - field=models.ForeignKey(blank=True, verbose_name='watermark image', null=True, to='photologue.Watermark', on_delete=models.CASCADE), - preserve_default=True, ), ] diff --git a/photologue/migrations/0002_photosize_data.py b/photologue/migrations/0002_photosize_data.py deleted file mode 100644 index 7bb9229..0000000 --- a/photologue/migrations/0002_photosize_data.py +++ /dev/null @@ -1,43 +0,0 @@ -# encoding: utf8 -from __future__ import unicode_literals - -from django.db import migrations, models - - -def initial_photosizes(apps, schema_editor): - - PhotoSize = apps.get_model('photologue', 'PhotoSize') - - # If there are already Photosizes, then we are upgrading an existing - # installation, we don't want to auto-create some PhotoSizes. - if PhotoSize.objects.all().count() > 0: - return - PhotoSize.objects.create(name='admin_thumbnail', - width=100, - height=75, - crop=True, - pre_cache=True, - increment_count=False) - PhotoSize.objects.create(name='thumbnail', - width=100, - height=75, - crop=True, - pre_cache=True, - increment_count=False) - PhotoSize.objects.create(name='display', - width=400, - crop=False, - pre_cache=True, - increment_count=True) - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue', '0001_initial'), - ('contenttypes', '0002_remove_content_type_name'), - ] - - operations = [ - migrations.RunPython(initial_photosizes), - ] diff --git a/photologue/migrations/0003_auto_20140822_1716.py b/photologue/migrations/0003_auto_20140822_1716.py deleted file mode 100644 index 16d1942..0000000 --- a/photologue/migrations/0003_auto_20140822_1716.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue', '0002_photosize_data'), - ] - - operations = [ - migrations.AlterField( - model_name='galleryupload', - name='title', - field=models.CharField(null=True, help_text='All uploaded photos will be given a title made up of this title + a sequential number.', max_length=50, verbose_name='title', blank=True), - ), - ] diff --git a/photologue/migrations/0004_auto_20140915_1259.py b/photologue/migrations/0004_auto_20140915_1259.py deleted file mode 100644 index 0202044..0000000 --- a/photologue/migrations/0004_auto_20140915_1259.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import sortedm2m.fields -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue', '0003_auto_20140822_1716'), - ] - - operations = [ - migrations.AlterField( - model_name='gallery', - name='photos', - field=sortedm2m.fields.SortedManyToManyField(to='photologue.Photo', related_name='galleries', null=True, verbose_name='photos', blank=True, help_text=None), - ), - migrations.AlterField( - model_name='photo', - name='effect', - field=models.ForeignKey(to='photologue.PhotoEffect', blank=True, related_name='photo_related', verbose_name='effect', null=True, on_delete=models.CASCADE), - ), - migrations.AlterField( - model_name='photosize', - name='effect', - field=models.ForeignKey(to='photologue.PhotoEffect', blank=True, related_name='photo_sizes', verbose_name='photo effect', null=True, on_delete=models.CASCADE), - ), - migrations.AlterField( - model_name='photosize', - name='watermark', - field=models.ForeignKey(to='photologue.Watermark', blank=True, related_name='photo_sizes', verbose_name='watermark image', null=True, on_delete=models.CASCADE), - ), - ] diff --git a/photologue/migrations/0005_auto_20141027_1552.py b/photologue/migrations/0005_auto_20141027_1552.py deleted file mode 100644 index 9f3d862..0000000 --- a/photologue/migrations/0005_auto_20141027_1552.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue', '0004_auto_20140915_1259'), - ] - - operations = [ - migrations.AlterField( - model_name='photo', - name='title', - field=models.CharField(unique=True, max_length=60, verbose_name='title'), - preserve_default=True, - ), - ] diff --git a/photologue/migrations/0006_auto_20141028_2005.py b/photologue/migrations/0006_auto_20141028_2005.py deleted file mode 100644 index 583c3b8..0000000 --- a/photologue/migrations/0006_auto_20141028_2005.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue', '0005_auto_20141027_1552'), - ] - - operations = [ - migrations.RemoveField( - model_name='galleryupload', - name='gallery', - ), - migrations.DeleteModel( - name='GalleryUpload', - ), - ] diff --git a/photologue/migrations/0007_auto_20150404_1737.py b/photologue/migrations/0007_auto_20150404_1737.py deleted file mode 100644 index b41490c..0000000 --- a/photologue/migrations/0007_auto_20150404_1737.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import sortedm2m.fields -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue', '0006_auto_20141028_2005'), - ] - - operations = [ - migrations.AlterField( - model_name='gallery', - name='photos', - field=sortedm2m.fields.SortedManyToManyField(help_text=None, related_name='galleries', verbose_name='photos', to='photologue.Photo', blank=True), - ), - migrations.AlterField( - model_name='gallery', - name='sites', - field=models.ManyToManyField(to='sites.Site', verbose_name='sites', blank=True), - ), - migrations.AlterField( - model_name='photo', - name='sites', - field=models.ManyToManyField(to='sites.Site', verbose_name='sites', blank=True), - ), - ] diff --git a/photologue/migrations/0008_auto_20150509_1557.py b/photologue/migrations/0008_auto_20150509_1557.py deleted file mode 100644 index 0baafd2..0000000 --- a/photologue/migrations/0008_auto_20150509_1557.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue', '0007_auto_20150404_1737'), - ] - - operations = [ - migrations.RemoveField( - model_name='gallery', - name='tags', - ), - migrations.RemoveField( - model_name='photo', - name='tags', - ), - ] diff --git a/photologue/migrations/0009_auto_20160102_0904.py b/photologue/migrations/0009_auto_20160102_0904.py deleted file mode 100644 index 4c64f11..0000000 --- a/photologue/migrations/0009_auto_20160102_0904.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-01-02 09:04 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue', '0008_auto_20150509_1557'), - ] - - operations = [ - migrations.AlterField( - model_name='photo', - name='date_taken', - field=models.DateTimeField(blank=True, help_text='Date image was taken; is obtained from the image EXIF data.', null=True, verbose_name='date taken'), - ), - ] diff --git a/photologue/migrations/0010_auto_20160105_1307.py b/photologue/migrations/0010_auto_20160105_1307.py deleted file mode 100644 index d466cae..0000000 --- a/photologue/migrations/0010_auto_20160105_1307.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9 on 2016-01-05 13:07 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue', '0009_auto_20160102_0904'), - ] - - operations = [ - migrations.AlterField( - model_name='gallery', - name='slug', - field=models.SlugField(help_text='A "slug" is a unique URL-friendly title for an object.', max_length=250, unique=True, verbose_name='title slug'), - ), - migrations.AlterField( - model_name='gallery', - name='title', - field=models.CharField(max_length=250, unique=True, verbose_name='title'), - ), - migrations.AlterField( - model_name='photo', - name='slug', - field=models.SlugField(help_text='A "slug" is a unique URL-friendly title for an object.', max_length=250, unique=True, verbose_name='slug'), - ), - migrations.AlterField( - model_name='photo', - name='title', - field=models.CharField(max_length=250, unique=True, verbose_name='title'), - ), - ] diff --git a/photologue/migrations/0011_auto_20190223_2138.py b/photologue/migrations/0011_auto_20190223_2138.py deleted file mode 100644 index 7bee4eb..0000000 --- a/photologue/migrations/0011_auto_20190223_2138.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-23 21:38 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue', '0010_auto_20160105_1307'), - ] - - operations = [ - migrations.AlterField( - model_name='photoeffect', - name='filters', - field=models.CharField(blank=True, help_text='Chain multiple filters using the following pattern "FILTER_ONE->FILTER_TWO->FILTER_THREE". Image filters will be applied in order. The following filters are available: BLUR, CONTOUR, DETAIL, EDGE_ENHANCE, EDGE_ENHANCE_MORE, EMBOSS, FIND_EDGES, Kernel, SHARPEN, SMOOTH, SMOOTH_MORE.', max_length=200, verbose_name='filters'), - ), - ] diff --git a/photologue/migrations/0012_auto_20220129_2207.py b/photologue/migrations/0012_auto_20220129_2207.py deleted file mode 100644 index 7ed2b9a..0000000 --- a/photologue/migrations/0012_auto_20220129_2207.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 3.2.11 on 2022-01-29 22:07 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue', '0011_auto_20190223_2138'), - ] - - operations = [ - migrations.RemoveField( - model_name='gallery', - name='sites', - ), - migrations.RemoveField( - model_name='photo', - name='effect', - ), - migrations.RemoveField( - model_name='photo', - name='sites', - ), - migrations.RemoveField( - model_name='photosize', - name='effect', - ), - migrations.RemoveField( - model_name='photosize', - name='watermark', - ), - migrations.DeleteModel( - name='PhotoEffect', - ), - migrations.DeleteModel( - name='Watermark', - ), - ] diff --git a/photologue/migrations/0013_alter_gallery_photos.py b/photologue/migrations/0013_alter_gallery_photos.py deleted file mode 100644 index ab5ecbc..0000000 --- a/photologue/migrations/0013_alter_gallery_photos.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.11 on 2022-01-30 07:09 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue', '0012_auto_20220129_2207'), - ] - - operations = [ - migrations.AlterField( - model_name='gallery', - name='photos', - field=models.ManyToManyField(blank=True, related_name='galleries', to='photologue.Photo', verbose_name='photos'), - ), - ] diff --git a/photologue/migrations/0014_merge_related.py b/photologue/migrations/0014_merge_related.py deleted file mode 100644 index 8dfa458..0000000 --- a/photologue/migrations/0014_merge_related.py +++ /dev/null @@ -1,96 +0,0 @@ -# Generated by Django 3.2.11 on 2022-01-30 08:32 - -import django.db.models.deletion -import django.utils.timezone -import taggit.managers -from django.conf import settings -from django.contrib.auth.models import User -from django.contrib.contenttypes.models import ContentType -from django.db import migrations, models -from django.template.defaultfilters import slugify - -numens = User.objects.get(username="Numens").id - -def migrate_related(apps, schema_editor): - Gallery = apps.get_model('photologue', 'Gallery') - Tag = apps.get_model('photologue', 'Tag') - TaggedItems = apps.get_model('taggit', 'TaggedItem') - ct_ext = ContentType.objects.get(app_label="photologue_custom", model="galleryextended") - for gallery in Gallery.objects.all(): - tagged_items = TaggedItems.objects.filter( - content_type_id=ct_ext.id, - object_id=gallery.extended.id - ) - tags = [tag.tag for tag in tagged_items.all()] - gallery.date_start = gallery.extended.date_start - gallery.date_end = gallery.extended.date_end - gallery.save() - for tag in tags: - try: - new_tag, created = Tag.objects.get_or_create( - name=tag.name.capitalize(), - slug=slugify(tag.name), - ) - if new_tag not in gallery.tags.all(): - gallery.tags.add(new_tag) - new_tag.save() - gallery.save() - except Exception: - continue - - Photo = apps.get_model('photologue', 'Photo') - for photo in Photo.objects.all(): - photo.owner = photo.extended.owner - photo.license = photo.extended.license - photo.save() - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('photologue', '0013_alter_gallery_photos'), - ] - - operations = [ - migrations.CreateModel( - name='Tag', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=250, unique=True, verbose_name='name')), - ('slug', models.SlugField(help_text='A "slug" is a unique URL-friendly title for an object.', max_length=250, unique=True, verbose_name='slug')), - ], - options={ - 'verbose_name': 'tag', - 'verbose_name_plural': 'tags', - 'ordering': ['name'], - }, - ), - migrations.AddField( - model_name='gallery', - name='date_end', - field=models.DateField(blank=True, null=True, verbose_name='end date'), - ), - migrations.AddField( - model_name='gallery', - name='date_start', - field=models.DateField(default=django.utils.timezone.now, verbose_name='start date'), - ), - migrations.AddField( - model_name='photo', - name='license', - field=models.CharField(blank=True, max_length=255, verbose_name='license'), - ), - migrations.AddField( - model_name='photo', - name='owner', - field=models.ForeignKey(default=numens, on_delete=django.db.models.deletion.CASCADE, to='auth.user', verbose_name='owner'), - preserve_default=False, - ), - migrations.AddField( - model_name='gallery', - name='tags', - field=models.ManyToManyField(blank=True, related_name='galleries', to='photologue.Tag', verbose_name='tags'), - ), - migrations.RunPython(migrate_related), - ] diff --git a/photologue_custom/__init__.py b/photologue_custom/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/photologue_custom/apps.py b/photologue_custom/apps.py deleted file mode 100644 index 55acba8..0000000 --- a/photologue_custom/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class PhotologueCustomConfig(AppConfig): - default_auto_field = 'django.db.models.AutoField' - name = 'photologue_custom' diff --git a/photologue_custom/migrations/0001_initial.py b/photologue_custom/migrations/0001_initial.py deleted file mode 100644 index 9fb5a1f..0000000 --- a/photologue_custom/migrations/0001_initial.py +++ /dev/null @@ -1,44 +0,0 @@ -# Generated by Django 2.2.24 on 2021-10-11 19:12 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import taggit.managers - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('photologue', '0011_auto_20190223_2138'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('taggit', '0002_auto_20150616_2121'), - ] - - operations = [ - migrations.CreateModel( - name='PhotoExtended', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='owner')), - ('photo', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='extented', to='photologue.Photo')), - ], - options={ - 'verbose_name': 'Extra fields', - 'verbose_name_plural': 'Extra fields', - }, - ), - migrations.CreateModel( - name='GalleryExtended', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('gallery', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='extended', to='photologue.Gallery')), - ('tags', taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')), - ], - options={ - 'verbose_name': 'Extra fields', - 'verbose_name_plural': 'Extra fields', - }, - ), - ] diff --git a/photologue_custom/migrations/0002_auto_20211011_1956.py b/photologue_custom/migrations/0002_auto_20211011_1956.py deleted file mode 100644 index d03ea2c..0000000 --- a/photologue_custom/migrations/0002_auto_20211011_1956.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.24 on 2021-10-11 19:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue_custom', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='galleryextended', - name='date_end', - field=models.DateField(blank=True, null=True, verbose_name='end date'), - ), - migrations.AddField( - model_name='galleryextended', - name='date_start', - field=models.DateField(blank=True, null=True, verbose_name='start date'), - ), - ] diff --git a/photologue_custom/migrations/0003_auto_20211013_1507.py b/photologue_custom/migrations/0003_auto_20211013_1507.py deleted file mode 100644 index a99c067..0000000 --- a/photologue_custom/migrations/0003_auto_20211013_1507.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 2.2.24 on 2021-10-13 15:07 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue_custom', '0002_auto_20211011_1956'), - ] - - operations = [ - migrations.AlterField( - model_name='galleryextended', - name='gallery', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='extended', to='photologue.Gallery'), - ), - migrations.AlterField( - model_name='photoextended', - name='photo', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='extended', to='photologue.Photo'), - ), - ] \ No newline at end of file diff --git a/photologue_custom/migrations/0004_photoextended_license.py b/photologue_custom/migrations/0004_photoextended_license.py deleted file mode 100644 index 87c6887..0000000 --- a/photologue_custom/migrations/0004_photoextended_license.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.24 on 2021-10-22 16:04 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('photologue_custom', '0003_auto_20211013_1507'), - ] - - operations = [ - migrations.AddField( - model_name='photoextended', - name='license', - field=models.CharField(blank=True, max_length=255, verbose_name='license'), - ), - ] diff --git a/photologue_custom/migrations/0005_auto_20220130_0953.py b/photologue_custom/migrations/0005_auto_20220130_0953.py deleted file mode 100644 index ef769ec..0000000 --- a/photologue_custom/migrations/0005_auto_20220130_0953.py +++ /dev/null @@ -1,27 +0,0 @@ -# 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', - ), - ] diff --git a/photologue_custom/migrations/__init__.py b/photologue_custom/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 -- GitLab From 2ef6dd2a44826e1d1c845fdcd4afdc7e02ea10fd Mon Sep 17 00:00:00 2001 From: Alexandre Iooss <erdnaxe@crans.org> Date: Sun, 30 Jan 2022 11:21:03 +0100 Subject: [PATCH 8/9] Remove date_added field in Gallery --- photologue/admin.py | 6 +++--- .../migrations/0002_auto_20220130_1020.py | 21 +++++++++++++++++++ photologue/models.py | 6 ++---- 3 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 photologue/migrations/0002_auto_20220130_1020.py diff --git a/photologue/admin.py b/photologue/admin.py index f398fc7..774ed8e 100644 --- a/photologue/admin.py +++ b/photologue/admin.py @@ -5,9 +5,9 @@ from .models import Gallery, Photo, Tag class GalleryAdmin(admin.ModelAdmin): - list_display = ('title', 'date_added', 'photo_count', 'is_public') - list_filter = ['date_added', 'is_public'] - date_hierarchy = 'date_added' + list_display = ('title', 'date_start', 'photo_count', 'is_public') + list_filter = ['date_start', 'is_public'] + date_hierarchy = 'date_start' prepopulated_fields = {'slug': ('title',)} model = Gallery autocomplete_fields = ['photos', 'tags'] diff --git a/photologue/migrations/0002_auto_20220130_1020.py b/photologue/migrations/0002_auto_20220130_1020.py new file mode 100644 index 0000000..21338b0 --- /dev/null +++ b/photologue/migrations/0002_auto_20220130_1020.py @@ -0,0 +1,21 @@ +# Generated by Django 3.2.11 on 2022-01-30 10:20 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('photologue', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='gallery', + options={'get_latest_by': 'date_start', 'ordering': ['-date_start'], 'verbose_name': 'gallery', 'verbose_name_plural': 'galleries'}, + ), + migrations.RemoveField( + model_name='gallery', + name='date_added', + ), + ] diff --git a/photologue/models.py b/photologue/models.py index 8b94e5c..b7e975c 100644 --- a/photologue/models.py +++ b/photologue/models.py @@ -136,8 +136,6 @@ class TagField(models.CharField): class Gallery(models.Model): - date_added = models.DateTimeField(_('date published'), - default=now) title = models.CharField(_('title'), max_length=250, unique=True) @@ -172,8 +170,8 @@ class Gallery(models.Model): blank=True) class Meta: - ordering = ['-date_added'] - get_latest_by = 'date_added' + ordering = ['-date_start'] + get_latest_by = 'date_start' verbose_name = _('gallery') verbose_name_plural = _('galleries') -- GitLab From a4faa7e04e54b82519836a17552d21c3553ff4eb Mon Sep 17 00:00:00 2001 From: Alexandre Iooss <erdnaxe@crans.org> Date: Sun, 30 Jan 2022 11:23:34 +0100 Subject: [PATCH 9/9] Fix Django Admin docs --- photo21/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/photo21/urls.py b/photo21/urls.py index 0538e1c..66d4912 100644 --- a/photo21/urls.py +++ b/photo21/urls.py @@ -25,8 +25,8 @@ urlpatterns = [ path('', include('photologue.urls', namespace='photologue')), path('accounts/', include('allauth.urls')), path('i18n/', include('django.conf.urls.i18n')), - path('admin/', admin.site.urls), path('admin/doc/', include('django.contrib.admindocs.urls')), + path('admin/', admin.site.urls), ] # In production media are served through NGINX with X-Accel-Redirect -- GitLab