Merge branch 'simplify_models' into 'master'
Simplify models See merge request bde/photo21!22
This commit is contained in:
commit
d7a39a0334
64 changed files with 732 additions and 1268 deletions
|
|
@ -79,8 +79,7 @@ production néccessite **une installation de Debian Bullseye ou plus récent**.
|
||||||
```
|
```
|
||||||
$ sudo apt install nginx git gettext uwsgi uwsgi-plugin-python3 python3-venv \
|
$ sudo apt install nginx git gettext uwsgi uwsgi-plugin-python3 python3-venv \
|
||||||
python3-certbot-nginx python3-django python3-django-crispy-forms \
|
python3-certbot-nginx python3-django python3-django-crispy-forms \
|
||||||
python3-django-taggit python3-pil python3-exifread python3-django-allauth \
|
python3-pil python3-exifread python3-django-allauth python3-docutils
|
||||||
python3-psycopg2 python3-docutils
|
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Clonage du dépot dans `/var/www/photos/photo21`**
|
2. **Clonage du dépot dans `/var/www/photos/photo21`**
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \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"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
|
@ -40,19 +40,19 @@ msgstr ""
|
||||||
msgid "hash"
|
msgid "hash"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photo21/settings.py:162
|
#: photo21/settings.py:161
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photo21/settings.py:163
|
#: photo21/settings.py:162
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photo21/settings.py:164
|
#: photo21/settings.py:163
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photo21/settings.py:165
|
#: photo21/settings.py:164
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -199,6 +199,16 @@ msgstr ""
|
||||||
msgid "If any problem, please contact the server owners at"
|
msgid "If any problem, please contact the server owners at"
|
||||||
msgstr ""
|
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
|
#: photo21/templates/account/signup.html:6
|
||||||
msgid "Signup"
|
msgid "Signup"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \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"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
|
@ -39,19 +39,19 @@ msgstr ""
|
||||||
msgid "hash"
|
msgid "hash"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photo21/settings.py:162
|
#: photo21/settings.py:161
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photo21/settings.py:163
|
#: photo21/settings.py:162
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photo21/settings.py:164
|
#: photo21/settings.py:163
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photo21/settings.py:165
|
#: photo21/settings.py:164
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -198,6 +198,16 @@ msgstr ""
|
||||||
msgid "If any problem, please contact the server owners at"
|
msgid "If any problem, please contact the server owners at"
|
||||||
msgstr ""
|
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
|
#: photo21/templates/account/signup.html:6
|
||||||
msgid "Signup"
|
msgid "Signup"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \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"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
|
@ -42,19 +42,19 @@ msgstr ""
|
||||||
msgid "hash"
|
msgid "hash"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photo21/settings.py:162
|
#: photo21/settings.py:160
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photo21/settings.py:163
|
#: photo21/settings.py:161
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photo21/settings.py:164
|
#: photo21/settings.py:162
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photo21/settings.py:165
|
#: photo21/settings.py:163
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -206,6 +206,18 @@ msgstr ""
|
||||||
msgid "If any problem, please contact the server owners at"
|
msgid "If any problem, please contact the server owners at"
|
||||||
msgstr "En cas de problème, contactez les administrateurs à"
|
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
|
#: photo21/templates/account/signup.html:6
|
||||||
msgid "Signup"
|
msgid "Signup"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -333,48 +345,3 @@ msgstr ""
|
||||||
#: photo21/templates/socialaccount/connections.html:54
|
#: photo21/templates/socialaccount/connections.html:54
|
||||||
msgid "Add a 3rd Party Account"
|
msgid "Add a 3rd Party Account"
|
||||||
msgstr ""
|
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"
|
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,7 @@ INSTALLED_APPS = [
|
||||||
'allauth.socialaccount',
|
'allauth.socialaccount',
|
||||||
'allauth_note_kfet',
|
'allauth_note_kfet',
|
||||||
'crispy_forms',
|
'crispy_forms',
|
||||||
'photologue_custom',
|
|
||||||
'photologue',
|
'photologue',
|
||||||
'taggit',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|
@ -156,8 +154,6 @@ USE_L10N = True
|
||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|
||||||
|
|
||||||
# Limit available languages to this subset
|
# Limit available languages to this subset
|
||||||
LANGUAGES = [
|
LANGUAGES = [
|
||||||
('de', _('German')),
|
('de', _('German')),
|
||||||
|
|
|
||||||
24
photo21/templates/account/logout.html
Normal file
24
photo21/templates/account/logout.html
Normal file
|
|
@ -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 %}
|
||||||
|
|
@ -22,11 +22,11 @@ from .views import IndexView, MediaAccess
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', IndexView.as_view(), name='index'),
|
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('accounts/', include('allauth.urls')),
|
||||||
path('i18n/', include('django.conf.urls.i18n')),
|
path('i18n/', include('django.conf.urls.i18n')),
|
||||||
path('admin/', admin.site.urls),
|
|
||||||
path('admin/doc/', include('django.contrib.admindocs.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
|
# In production media are served through NGINX with X-Accel-Redirect
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,41 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from .models import Gallery, Photo
|
from .models import Gallery, Photo, Tag
|
||||||
|
|
||||||
|
|
||||||
class GalleryAdmin(admin.ModelAdmin):
|
class GalleryAdmin(admin.ModelAdmin):
|
||||||
list_display = ('title', 'date_added', 'photo_count', 'is_public')
|
list_display = ('title', 'date_start', 'photo_count', 'is_public')
|
||||||
list_filter = ['date_added', 'is_public']
|
list_filter = ['date_start', 'is_public']
|
||||||
date_hierarchy = 'date_added'
|
date_hierarchy = 'date_start'
|
||||||
prepopulated_fields = {'slug': ('title',)}
|
prepopulated_fields = {'slug': ('title',)}
|
||||||
model = Gallery
|
model = Gallery
|
||||||
autocomplete_fields = ['photos', ]
|
autocomplete_fields = ['photos', 'tags']
|
||||||
search_fields = ['title', ]
|
search_fields = ['title', ]
|
||||||
|
|
||||||
|
|
||||||
class PhotoAdmin(admin.ModelAdmin):
|
class PhotoAdmin(admin.ModelAdmin):
|
||||||
list_display = ('title', 'date_taken', 'date_added',
|
list_display = ('title', 'date_taken', 'date_added',
|
||||||
'is_public', 'view_count', 'admin_thumbnail')
|
'is_public', 'view_count', 'admin_thumbnail', 'get_owner')
|
||||||
list_filter = ['date_added', 'is_public']
|
list_filter = ['date_added', 'is_public', 'owner']
|
||||||
search_fields = ['title', 'slug', 'caption']
|
search_fields = ['title', 'slug', 'caption']
|
||||||
list_per_page = 10
|
list_per_page = 10
|
||||||
prepopulated_fields = {'slug': ('title',)}
|
prepopulated_fields = {'slug': ('title',)}
|
||||||
readonly_fields = ('date_taken',)
|
readonly_fields = ('date_taken',)
|
||||||
model = Photo
|
model = Photo
|
||||||
|
|
||||||
|
def get_owner(self, obj):
|
||||||
|
return obj.owner.username
|
||||||
|
get_owner.admin_order_field = 'owner'
|
||||||
|
get_owner.short_description = _('owner')
|
||||||
|
|
||||||
|
|
||||||
|
class TagAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('name',)
|
||||||
|
search_fields = ('name',)
|
||||||
|
model = Tag
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(Gallery, GalleryAdmin)
|
||||||
|
admin.site.register(Photo, PhotoAdmin)
|
||||||
|
admin.site.register(Tag, TagAdmin)
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,8 @@ from crispy_forms.layout import Div, Layout, Submit
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from photologue.models import Gallery
|
|
||||||
from taggit.models import Tag
|
|
||||||
|
|
||||||
from .models import GalleryExtended
|
from .models import Gallery, Tag
|
||||||
|
|
||||||
|
|
||||||
class GalleryChoiceField(forms.ModelChoiceField):
|
|
||||||
def label_from_instance(self, obj):
|
|
||||||
"""Show gallery event date."""
|
|
||||||
if hasattr(obj, 'extended'):
|
|
||||||
return f"{ obj.title } ({obj.extended.date_start})"
|
|
||||||
else:
|
|
||||||
return obj.title
|
|
||||||
|
|
||||||
|
|
||||||
class UploadForm(forms.Form):
|
class UploadForm(forms.Form):
|
||||||
|
|
@ -29,7 +18,7 @@ class UploadForm(forms.Form):
|
||||||
'class': 'mb-3',
|
'class': 'mb-3',
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
gallery = GalleryChoiceField(
|
gallery = forms.ModelChoiceField(
|
||||||
Gallery.objects.all(),
|
Gallery.objects.all(),
|
||||||
label=_('Gallery'),
|
label=_('Gallery'),
|
||||||
required=False,
|
required=False,
|
||||||
|
|
@ -100,12 +89,12 @@ class UploadForm(forms.Form):
|
||||||
if not gallery:
|
if not gallery:
|
||||||
# Create new gallery
|
# Create new gallery
|
||||||
title = self.cleaned_data.get('new_gallery_title')
|
title = self.cleaned_data.get('new_gallery_title')
|
||||||
gallery = Gallery.objects.create(title=title, slug=slugify(title))
|
gallery = Gallery.objects.create(
|
||||||
ext = GalleryExtended.objects.create(
|
title=title,
|
||||||
gallery=gallery,
|
slug=slugify(title),
|
||||||
date_start=self.cleaned_data['new_gallery_date_start'],
|
date_start=self.cleaned_data['new_gallery_date_start'],
|
||||||
date_end=self.cleaned_data['new_gallery_date_end'],
|
date_end=self.cleaned_data['new_gallery_date_end'],
|
||||||
)
|
)
|
||||||
for tag in self.cleaned_data['new_gallery_tags']:
|
for tag in self.cleaned_data['new_gallery_tags']:
|
||||||
ext.tags.add(tag)
|
gallery.tags.add(tag)
|
||||||
return gallery
|
return gallery
|
||||||
|
|
@ -11,7 +11,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Photologue\n"
|
"Project-Id-Version: Photologue\n"
|
||||||
"Report-Msgid-Bugs-To: \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"
|
"PO-Revision-Date: 2017-12-03 14:47+0000\n"
|
||||||
"Last-Translator: Richard Barran <richard@arbee-design.co.uk>\n"
|
"Last-Translator: Richard Barran <richard@arbee-design.co.uk>\n"
|
||||||
"Language-Team: German (http://www.transifex.com/richardbarran/django-"
|
"Language-Team: German (http://www.transifex.com/richardbarran/django-"
|
||||||
|
|
@ -22,75 +22,79 @@ msgstr ""
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\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"
|
msgid "Very Low"
|
||||||
msgstr "Sehr niedrig"
|
msgstr "Sehr niedrig"
|
||||||
|
|
||||||
#: photologue/models.py:87
|
#: photologue/models.py:85
|
||||||
msgid "Low"
|
msgid "Low"
|
||||||
msgstr "Niedrig"
|
msgstr "Niedrig"
|
||||||
|
|
||||||
#: photologue/models.py:88
|
#: photologue/models.py:86
|
||||||
msgid "Medium-Low"
|
msgid "Medium-Low"
|
||||||
msgstr "Mittel-niedrig"
|
msgstr "Mittel-niedrig"
|
||||||
|
|
||||||
#: photologue/models.py:89
|
#: photologue/models.py:87
|
||||||
msgid "Medium"
|
msgid "Medium"
|
||||||
msgstr "Mittel"
|
msgstr "Mittel"
|
||||||
|
|
||||||
#: photologue/models.py:90
|
#: photologue/models.py:88
|
||||||
msgid "Medium-High"
|
msgid "Medium-High"
|
||||||
msgstr "Mittel-hoch"
|
msgstr "Mittel-hoch"
|
||||||
|
|
||||||
#: photologue/models.py:91
|
#: photologue/models.py:89
|
||||||
msgid "High"
|
msgid "High"
|
||||||
msgstr "Hoch"
|
msgstr "Hoch"
|
||||||
|
|
||||||
#: photologue/models.py:92
|
#: photologue/models.py:90
|
||||||
msgid "Very High"
|
msgid "Very High"
|
||||||
msgstr "Sehr hoch"
|
msgstr "Sehr hoch"
|
||||||
|
|
||||||
#: photologue/models.py:97
|
#: photologue/models.py:95
|
||||||
msgid "Top"
|
msgid "Top"
|
||||||
msgstr "Oben"
|
msgstr "Oben"
|
||||||
|
|
||||||
#: photologue/models.py:98
|
#: photologue/models.py:96
|
||||||
msgid "Right"
|
msgid "Right"
|
||||||
msgstr "Rechts"
|
msgstr "Rechts"
|
||||||
|
|
||||||
#: photologue/models.py:99
|
#: photologue/models.py:97
|
||||||
msgid "Bottom"
|
msgid "Bottom"
|
||||||
msgstr "Unten"
|
msgstr "Unten"
|
||||||
|
|
||||||
#: photologue/models.py:100
|
#: photologue/models.py:98
|
||||||
msgid "Left"
|
msgid "Left"
|
||||||
msgstr "Links"
|
msgstr "Links"
|
||||||
|
|
||||||
#: photologue/models.py:101
|
#: photologue/models.py:99
|
||||||
msgid "Center (Default)"
|
msgid "Center (Default)"
|
||||||
msgstr "Mitte (Standard)"
|
msgstr "Mitte (Standard)"
|
||||||
|
|
||||||
#: photologue/models.py:105
|
#: photologue/models.py:103
|
||||||
msgid "Flip left to right"
|
msgid "Flip left to right"
|
||||||
msgstr "Horizontal spiegeln"
|
msgstr "Horizontal spiegeln"
|
||||||
|
|
||||||
#: photologue/models.py:106
|
#: photologue/models.py:104
|
||||||
msgid "Flip top to bottom"
|
msgid "Flip top to bottom"
|
||||||
msgstr "Vertikal spiegeln"
|
msgstr "Vertikal spiegeln"
|
||||||
|
|
||||||
#: photologue/models.py:107
|
#: photologue/models.py:105
|
||||||
msgid "Rotate 90 degrees counter-clockwise"
|
msgid "Rotate 90 degrees counter-clockwise"
|
||||||
msgstr "Um 90° nach links drehen"
|
msgstr "Um 90° nach links drehen"
|
||||||
|
|
||||||
#: photologue/models.py:108
|
#: photologue/models.py:106
|
||||||
msgid "Rotate 90 degrees clockwise"
|
msgid "Rotate 90 degrees clockwise"
|
||||||
msgstr "Um 90° nach rechts drehen"
|
msgstr "Um 90° nach rechts drehen"
|
||||||
|
|
||||||
#: photologue/models.py:109
|
#: photologue/models.py:107
|
||||||
msgid "Rotate 180 degrees"
|
msgid "Rotate 180 degrees"
|
||||||
msgstr "Um 180° drehen"
|
msgstr "Um 180° drehen"
|
||||||
|
|
||||||
#: photologue/models.py:119
|
#: photologue/models.py:117
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Chain multiple filters using the following pattern \"FILTER_ONE->FILTER_TWO-"
|
"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 "
|
"\". Bildfilter werden nach der Reihe angewendet. Folgende Filter sind "
|
||||||
"verfügbar: %s."
|
"verfügbar: %s."
|
||||||
|
|
||||||
#: photologue/models.py:141
|
#: photologue/models.py:139
|
||||||
msgid "date published"
|
msgid "date published"
|
||||||
msgstr "Veröffentlichungsdatum"
|
msgstr "Veröffentlichungsdatum"
|
||||||
|
|
||||||
#: photologue/models.py:143 photologue/models.py:474
|
#: photologue/models.py:141 photologue/models.py:485
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "Titel"
|
msgstr "Titel"
|
||||||
|
|
||||||
#: photologue/models.py:146
|
#: photologue/models.py:144
|
||||||
msgid "title slug"
|
msgid "title slug"
|
||||||
msgstr "Kurztitel"
|
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."
|
msgid "A \"slug\" is a unique URL-friendly title for an object."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Ein Kurztitel (\"slug\") ist ein eindeutiger, URL-geeigneter Titel für ein "
|
"Ein Kurztitel (\"slug\") ist ein eindeutiger, URL-geeigneter Titel für ein "
|
||||||
"Objekt."
|
"Objekt."
|
||||||
|
|
||||||
#: photologue/models.py:150
|
#: photologue/models.py:150
|
||||||
|
msgid "start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: photologue/models.py:155
|
||||||
|
msgid "end date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: photologue/models.py:157
|
||||||
msgid "description"
|
msgid "description"
|
||||||
msgstr "Beschreibung"
|
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"
|
msgid "is public"
|
||||||
msgstr "ist öffentlich"
|
msgstr "ist öffentlich"
|
||||||
|
|
||||||
#: photologue/models.py:154
|
#: photologue/models.py:167
|
||||||
msgid "Public galleries will be displayed in the default views."
|
msgid "Public galleries will be displayed in the default views."
|
||||||
msgstr "Öffentliche Galerien werden in den Standard-Views angezeigt."
|
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"
|
msgid "photos"
|
||||||
msgstr "Fotos"
|
msgstr "Fotos"
|
||||||
|
|
||||||
#: photologue/models.py:166
|
#: photologue/models.py:177
|
||||||
msgid "gallery"
|
msgid "gallery"
|
||||||
msgstr "Galerie"
|
msgstr "Galerie"
|
||||||
|
|
||||||
#: photologue/models.py:167
|
#: photologue/models.py:178
|
||||||
msgid "galleries"
|
msgid "galleries"
|
||||||
msgstr "Galerien"
|
msgstr "Galerien"
|
||||||
|
|
||||||
#: photologue/models.py:202
|
#: photologue/models.py:213
|
||||||
msgid "count"
|
msgid "count"
|
||||||
msgstr "Anzahl"
|
msgstr "Anzahl"
|
||||||
|
|
||||||
#: photologue/models.py:210
|
#: photologue/models.py:221
|
||||||
msgid "image"
|
msgid "image"
|
||||||
msgstr "Bild"
|
msgstr "Bild"
|
||||||
|
|
||||||
#: photologue/models.py:213
|
#: photologue/models.py:224
|
||||||
msgid "date taken"
|
msgid "date taken"
|
||||||
msgstr "Aufnahmedatum"
|
msgstr "Aufnahmedatum"
|
||||||
|
|
||||||
#: photologue/models.py:216
|
#: photologue/models.py:227
|
||||||
msgid "Date image was taken; is obtained from the image EXIF data."
|
msgid "Date image was taken; is obtained from the image EXIF data."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Datum, an dem das Foto geschossen wurde; ausgelesen aus den EXIF-Daten."
|
"Datum, an dem das Foto geschossen wurde; ausgelesen aus den EXIF-Daten."
|
||||||
|
|
||||||
#: photologue/models.py:217
|
#: photologue/models.py:228
|
||||||
msgid "view count"
|
msgid "view count"
|
||||||
msgstr "Anzahl an Aufrufen"
|
msgstr "Anzahl an Aufrufen"
|
||||||
|
|
||||||
#: photologue/models.py:220
|
#: photologue/models.py:231
|
||||||
msgid "crop from"
|
msgid "crop from"
|
||||||
msgstr "Beschneiden von"
|
msgstr "Beschneiden von"
|
||||||
|
|
||||||
#: photologue/models.py:243
|
#: photologue/models.py:254
|
||||||
msgid "An \"admin_thumbnail\" photo size has not been defined."
|
msgid "An \"admin_thumbnail\" photo size has not been defined."
|
||||||
msgstr "Es ist keine Fotogröße \"admin_thumbnail\" definiert."
|
msgstr "Es ist keine Fotogröße \"admin_thumbnail\" definiert."
|
||||||
|
|
||||||
#: photologue/models.py:250
|
#: photologue/models.py:261
|
||||||
msgid "Thumbnail"
|
msgid "Thumbnail"
|
||||||
msgstr "Vorschaubild"
|
msgstr "Vorschaubild"
|
||||||
|
|
||||||
#: photologue/models.py:477
|
#: photologue/models.py:488 photologue/models.py:696
|
||||||
msgid "slug"
|
msgid "slug"
|
||||||
msgstr "Kurztitel"
|
msgstr "Kurztitel"
|
||||||
|
|
||||||
#: photologue/models.py:481
|
#: photologue/models.py:492
|
||||||
msgid "caption"
|
msgid "caption"
|
||||||
msgstr "Bildunterschrift"
|
msgstr "Bildunterschrift"
|
||||||
|
|
||||||
#: photologue/models.py:483
|
#: photologue/models.py:494
|
||||||
msgid "date added"
|
msgid "date added"
|
||||||
msgstr "Datum des Eintrags"
|
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."
|
msgid "Public photographs will be displayed in the default views."
|
||||||
msgstr "Öffentliche Fotos werden in den Standard-Views angezeigt."
|
msgstr "Öffentliche Fotos werden in den Standard-Views angezeigt."
|
||||||
|
|
||||||
#: photologue/models.py:494
|
#: photologue/models.py:513
|
||||||
msgid "photo"
|
msgid "photo"
|
||||||
msgstr "Foto"
|
msgstr "Foto"
|
||||||
|
|
||||||
#: photologue/models.py:556
|
#: photologue/models.py:575 photologue/models.py:691
|
||||||
msgid "name"
|
msgid "name"
|
||||||
msgstr "Name"
|
msgstr "Name"
|
||||||
|
|
||||||
#: photologue/models.py:560
|
#: photologue/models.py:579
|
||||||
msgid ""
|
msgid ""
|
||||||
"Photo size name should contain only letters, numbers and underscores. "
|
"Photo size name should contain only letters, numbers and underscores. "
|
||||||
"Examples: \"thumbnail\", \"display\", \"small\", \"main_page_widget\"."
|
"Examples: \"thumbnail\", \"display\", \"small\", \"main_page_widget\"."
|
||||||
|
|
@ -209,41 +229,41 @@ msgstr ""
|
||||||
"enthalten. Beispiele: \"thumbnail\", \"display\", \"small\", "
|
"enthalten. Beispiele: \"thumbnail\", \"display\", \"small\", "
|
||||||
"\"main_page_widget\"."
|
"\"main_page_widget\"."
|
||||||
|
|
||||||
#: photologue/models.py:567
|
#: photologue/models.py:586
|
||||||
msgid "width"
|
msgid "width"
|
||||||
msgstr "Breite"
|
msgstr "Breite"
|
||||||
|
|
||||||
#: photologue/models.py:570
|
#: photologue/models.py:589
|
||||||
msgid ""
|
msgid ""
|
||||||
"If width is set to \"0\" the image will be scaled to the supplied height."
|
"If width is set to \"0\" the image will be scaled to the supplied height."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Wenn die Breite auf \"0\" gesetzt ist, wird das Bild proportional auf die "
|
"Wenn die Breite auf \"0\" gesetzt ist, wird das Bild proportional auf die "
|
||||||
"angebene Höhe skaliert."
|
"angebene Höhe skaliert."
|
||||||
|
|
||||||
#: photologue/models.py:571
|
#: photologue/models.py:590
|
||||||
msgid "height"
|
msgid "height"
|
||||||
msgstr "Höhe"
|
msgstr "Höhe"
|
||||||
|
|
||||||
#: photologue/models.py:574
|
#: photologue/models.py:593
|
||||||
msgid ""
|
msgid ""
|
||||||
"If height is set to \"0\" the image will be scaled to the supplied width"
|
"If height is set to \"0\" the image will be scaled to the supplied width"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Wenn die Höhe auf \"0\" gesetzt ist, wird das Bild proportional auf die "
|
"Wenn die Höhe auf \"0\" gesetzt ist, wird das Bild proportional auf die "
|
||||||
"angebene Breite skaliert."
|
"angebene Breite skaliert."
|
||||||
|
|
||||||
#: photologue/models.py:575
|
#: photologue/models.py:594
|
||||||
msgid "quality"
|
msgid "quality"
|
||||||
msgstr "Qualität"
|
msgstr "Qualität"
|
||||||
|
|
||||||
#: photologue/models.py:578
|
#: photologue/models.py:597
|
||||||
msgid "JPEG image quality."
|
msgid "JPEG image quality."
|
||||||
msgstr "JPEG-Bildqualität"
|
msgstr "JPEG-Bildqualität"
|
||||||
|
|
||||||
#: photologue/models.py:579
|
#: photologue/models.py:598
|
||||||
msgid "upscale images?"
|
msgid "upscale images?"
|
||||||
msgstr "Bilder hochskalieren?"
|
msgstr "Bilder hochskalieren?"
|
||||||
|
|
||||||
#: photologue/models.py:581
|
#: photologue/models.py:600
|
||||||
msgid ""
|
msgid ""
|
||||||
"If selected the image will be scaled up if necessary to fit the supplied "
|
"If selected the image will be scaled up if necessary to fit the supplied "
|
||||||
"dimensions. Cropped sizes will be upscaled regardless of this setting."
|
"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 "
|
"Beschnittene Größen werden unabhängig von dieser Einstellung bei Bedarf "
|
||||||
"hochskaliert."
|
"hochskaliert."
|
||||||
|
|
||||||
#: photologue/models.py:585
|
#: photologue/models.py:604
|
||||||
msgid "crop to fit?"
|
msgid "crop to fit?"
|
||||||
msgstr "Zuschneiden?"
|
msgstr "Zuschneiden?"
|
||||||
|
|
||||||
#: photologue/models.py:587
|
#: photologue/models.py:606
|
||||||
msgid ""
|
msgid ""
|
||||||
"If selected the image will be scaled and cropped to fit the supplied "
|
"If selected the image will be scaled and cropped to fit the supplied "
|
||||||
"dimensions."
|
"dimensions."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Soll das Bild auf das angegebene Format skaliert und beschnitten werden?"
|
"Soll das Bild auf das angegebene Format skaliert und beschnitten werden?"
|
||||||
|
|
||||||
#: photologue/models.py:589
|
#: photologue/models.py:608
|
||||||
msgid "pre-cache?"
|
msgid "pre-cache?"
|
||||||
msgstr "Vorausspeichern?"
|
msgstr "Vorausspeichern?"
|
||||||
|
|
||||||
#: photologue/models.py:591
|
#: photologue/models.py:610
|
||||||
msgid "If selected this photo size will be pre-cached as photos are added."
|
msgid "If selected this photo size will be pre-cached as photos are added."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Soll diese Bildgröße im Voraus gespeichert (pre-cached) werden, wenn Fotos "
|
"Soll diese Bildgröße im Voraus gespeichert (pre-cached) werden, wenn Fotos "
|
||||||
"hinzugefügt werden?"
|
"hinzugefügt werden?"
|
||||||
|
|
||||||
#: photologue/models.py:592
|
#: photologue/models.py:611
|
||||||
msgid "increment view count?"
|
msgid "increment view count?"
|
||||||
msgstr "Bildzähler?"
|
msgstr "Bildzähler?"
|
||||||
|
|
||||||
#: photologue/models.py:594
|
#: photologue/models.py:613
|
||||||
msgid ""
|
msgid ""
|
||||||
"If selected the image's \"view_count\" will be incremented when this photo "
|
"If selected the image's \"view_count\" will be incremented when this photo "
|
||||||
"size is displayed."
|
"size is displayed."
|
||||||
|
|
@ -285,32 +305,32 @@ msgstr ""
|
||||||
"Soll der Ansichts-Zähler (view-count) hochgezählt werden, wenn ein Foto "
|
"Soll der Ansichts-Zähler (view-count) hochgezählt werden, wenn ein Foto "
|
||||||
"dieser Größe angezeigt wird?"
|
"dieser Größe angezeigt wird?"
|
||||||
|
|
||||||
#: photologue/models.py:599
|
#: photologue/models.py:618
|
||||||
msgid "photo size"
|
msgid "photo size"
|
||||||
msgstr "Foto-Größe"
|
msgstr "Foto-Größe"
|
||||||
|
|
||||||
#: photologue/models.py:600
|
#: photologue/models.py:619
|
||||||
msgid "photo sizes"
|
msgid "photo sizes"
|
||||||
msgstr "Foto-Größen"
|
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."
|
msgid "Can only crop photos if both width and height dimensions are set."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Fotos können nur zugeschnitten werden, wenn Breite und Höhe angegeben sind."
|
"Fotos können nur zugeschnitten werden, wenn Breite und Höhe angegeben sind."
|
||||||
|
|
||||||
#: photologue_custom/admin.py:43 photologue_custom/models.py:51
|
#: photologue/models.py:702
|
||||||
msgid "owner"
|
msgid "tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:34
|
#: photologue_custom/forms.py:22
|
||||||
msgid "Gallery"
|
msgid "Gallery"
|
||||||
msgstr "Galerie"
|
msgstr "Galerie"
|
||||||
|
|
||||||
#: photologue_custom/forms.py:36
|
#: photologue_custom/forms.py:24
|
||||||
msgid "-- Create a new gallery --"
|
msgid "-- Create a new gallery --"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:37
|
#: photologue_custom/forms.py:25
|
||||||
msgid ""
|
msgid ""
|
||||||
"Select a gallery to add these images to. Leave this empty to create a new "
|
"Select a gallery to add these images to. Leave this empty to create a new "
|
||||||
"gallery from the supplied title."
|
"gallery from the supplied title."
|
||||||
|
|
@ -318,59 +338,43 @@ msgstr ""
|
||||||
"Wähle eine Galerie aus, zu der diese Bilder hinzugefügt werden sollen. Lasse "
|
"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."
|
"dieses Feld leer, um eine neue Galerie mit dem angegeben Titel zu erzeugen."
|
||||||
|
|
||||||
#: photologue_custom/forms.py:41
|
#: photologue_custom/forms.py:29
|
||||||
#, fuzzy
|
|
||||||
#| msgid "View all galleries"
|
|
||||||
msgid "New gallery title"
|
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"
|
msgid "New gallery event start date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:51
|
#: photologue_custom/forms.py:39
|
||||||
msgid "New gallery event end date"
|
msgid "New gallery event end date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:57
|
#: photologue_custom/forms.py:45
|
||||||
#, fuzzy
|
|
||||||
#| msgid "gallery"
|
|
||||||
msgid "New gallery tags"
|
msgid "New gallery tags"
|
||||||
msgstr "Galerie"
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:59
|
#: photologue_custom/forms.py:47
|
||||||
msgid ""
|
msgid ""
|
||||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:76
|
#: photologue_custom/forms.py:64
|
||||||
#: photologue_custom/templates/photologue/upload.html:6
|
#: photologue_custom/templates/photologue/upload.html:6
|
||||||
#: photologue_custom/templates/photologue/upload.html:73
|
#: photologue_custom/templates/photologue/upload.html:73
|
||||||
msgid "Upload"
|
msgid "Upload"
|
||||||
msgstr "Hochladen"
|
msgstr "Hochladen"
|
||||||
|
|
||||||
#: photologue_custom/forms.py:82
|
#: photologue_custom/forms.py:70
|
||||||
msgid "A gallery with that title already exists."
|
msgid "A gallery with that title already exists."
|
||||||
msgstr "Es existiert bereits eine Gallerie mit diesem Titel."
|
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."
|
msgid "Select an existing gallery, or enter a title for a new gallery."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Wähle eine existierende Galerie aus oder gib einen Titel für eine neue "
|
"Wähle eine existierende Galerie aus oder gib einen Titel für eine neue "
|
||||||
"Galerie ein."
|
"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:7
|
||||||
#: photologue_custom/templates/photologue/gallery_archive.html:12
|
#: photologue_custom/templates/photologue/gallery_archive.html:12
|
||||||
msgid "Latest photo galleries"
|
msgid "Latest photo galleries"
|
||||||
|
|
@ -403,16 +407,12 @@ msgid "to"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/templates/photologue/gallery_detail.html:57
|
#: photologue_custom/templates/photologue/gallery_detail.html:57
|
||||||
#, fuzzy
|
|
||||||
#| msgid "All photos"
|
|
||||||
msgid "All pictures"
|
msgid "All pictures"
|
||||||
msgstr "Alle Fotos"
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/templates/photologue/gallery_detail.html:78
|
#: photologue_custom/templates/photologue/gallery_detail.html:78
|
||||||
#, fuzzy
|
|
||||||
#| msgid "View all galleries"
|
|
||||||
msgid "Download all gallery"
|
msgid "Download all gallery"
|
||||||
msgstr "Zeige alle Galerien."
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/templates/photologue/photo_detail.html:13
|
#: photologue_custom/templates/photologue/photo_detail.html:13
|
||||||
msgid "Published"
|
msgid "Published"
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Photologue\n"
|
"Project-Id-Version: Photologue\n"
|
||||||
"Report-Msgid-Bugs-To: \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"
|
"PO-Revision-Date: 2017-12-03 14:46+0000\n"
|
||||||
"Last-Translator: Richard Barran <richard@arbee-design.co.uk>\n"
|
"Last-Translator: Richard Barran <richard@arbee-design.co.uk>\n"
|
||||||
"Language-Team: Spanish (Spain) (http://www.transifex.com/richardbarran/"
|
"Language-Team: Spanish (Spain) (http://www.transifex.com/richardbarran/"
|
||||||
|
|
@ -23,75 +23,79 @@ msgstr ""
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\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"
|
msgid "Very Low"
|
||||||
msgstr "Muy bajo"
|
msgstr "Muy bajo"
|
||||||
|
|
||||||
#: photologue/models.py:87
|
#: photologue/models.py:85
|
||||||
msgid "Low"
|
msgid "Low"
|
||||||
msgstr "Bajo"
|
msgstr "Bajo"
|
||||||
|
|
||||||
#: photologue/models.py:88
|
#: photologue/models.py:86
|
||||||
msgid "Medium-Low"
|
msgid "Medium-Low"
|
||||||
msgstr "Medio-bajo"
|
msgstr "Medio-bajo"
|
||||||
|
|
||||||
#: photologue/models.py:89
|
#: photologue/models.py:87
|
||||||
msgid "Medium"
|
msgid "Medium"
|
||||||
msgstr "Medio"
|
msgstr "Medio"
|
||||||
|
|
||||||
#: photologue/models.py:90
|
#: photologue/models.py:88
|
||||||
msgid "Medium-High"
|
msgid "Medium-High"
|
||||||
msgstr "Medio-alto"
|
msgstr "Medio-alto"
|
||||||
|
|
||||||
#: photologue/models.py:91
|
#: photologue/models.py:89
|
||||||
msgid "High"
|
msgid "High"
|
||||||
msgstr "Alto"
|
msgstr "Alto"
|
||||||
|
|
||||||
#: photologue/models.py:92
|
#: photologue/models.py:90
|
||||||
msgid "Very High"
|
msgid "Very High"
|
||||||
msgstr "Muy alto"
|
msgstr "Muy alto"
|
||||||
|
|
||||||
#: photologue/models.py:97
|
#: photologue/models.py:95
|
||||||
msgid "Top"
|
msgid "Top"
|
||||||
msgstr "Arriba"
|
msgstr "Arriba"
|
||||||
|
|
||||||
#: photologue/models.py:98
|
#: photologue/models.py:96
|
||||||
msgid "Right"
|
msgid "Right"
|
||||||
msgstr "Derecha"
|
msgstr "Derecha"
|
||||||
|
|
||||||
#: photologue/models.py:99
|
#: photologue/models.py:97
|
||||||
msgid "Bottom"
|
msgid "Bottom"
|
||||||
msgstr "Abajo"
|
msgstr "Abajo"
|
||||||
|
|
||||||
#: photologue/models.py:100
|
#: photologue/models.py:98
|
||||||
msgid "Left"
|
msgid "Left"
|
||||||
msgstr "Izquierda"
|
msgstr "Izquierda"
|
||||||
|
|
||||||
#: photologue/models.py:101
|
#: photologue/models.py:99
|
||||||
msgid "Center (Default)"
|
msgid "Center (Default)"
|
||||||
msgstr "Centro (por defecto)"
|
msgstr "Centro (por defecto)"
|
||||||
|
|
||||||
#: photologue/models.py:105
|
#: photologue/models.py:103
|
||||||
msgid "Flip left to right"
|
msgid "Flip left to right"
|
||||||
msgstr "Voltear de izquerda a derecha"
|
msgstr "Voltear de izquerda a derecha"
|
||||||
|
|
||||||
#: photologue/models.py:106
|
#: photologue/models.py:104
|
||||||
msgid "Flip top to bottom"
|
msgid "Flip top to bottom"
|
||||||
msgstr "Voltear de arriba a abajo"
|
msgstr "Voltear de arriba a abajo"
|
||||||
|
|
||||||
#: photologue/models.py:107
|
#: photologue/models.py:105
|
||||||
msgid "Rotate 90 degrees counter-clockwise"
|
msgid "Rotate 90 degrees counter-clockwise"
|
||||||
msgstr "Rotar 90 grados en sentido horario"
|
msgstr "Rotar 90 grados en sentido horario"
|
||||||
|
|
||||||
#: photologue/models.py:108
|
#: photologue/models.py:106
|
||||||
msgid "Rotate 90 degrees clockwise"
|
msgid "Rotate 90 degrees clockwise"
|
||||||
msgstr "Rotar 90 grados en sentido antihorario"
|
msgstr "Rotar 90 grados en sentido antihorario"
|
||||||
|
|
||||||
#: photologue/models.py:109
|
#: photologue/models.py:107
|
||||||
msgid "Rotate 180 degrees"
|
msgid "Rotate 180 degrees"
|
||||||
msgstr "Rotar 180 grados"
|
msgstr "Rotar 180 grados"
|
||||||
|
|
||||||
#: photologue/models.py:119
|
#: photologue/models.py:117
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Chain multiple filters using the following pattern \"FILTER_ONE->FILTER_TWO-"
|
"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 "
|
">FILTRO_DOS->FILTRO_TRES\". Los filtros de imagen se aplicarán en orden. Los "
|
||||||
"siguientes filtros están disponibles: %s."
|
"siguientes filtros están disponibles: %s."
|
||||||
|
|
||||||
#: photologue/models.py:141
|
#: photologue/models.py:139
|
||||||
msgid "date published"
|
msgid "date published"
|
||||||
msgstr "fecha de publicación"
|
msgstr "fecha de publicación"
|
||||||
|
|
||||||
#: photologue/models.py:143 photologue/models.py:474
|
#: photologue/models.py:141 photologue/models.py:485
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "título"
|
msgstr "título"
|
||||||
|
|
||||||
#: photologue/models.py:146
|
#: photologue/models.py:144
|
||||||
msgid "title slug"
|
msgid "title slug"
|
||||||
msgstr "título 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."
|
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."
|
msgstr "Un \"slug\" es un único título URL-amigable para un objeto."
|
||||||
|
|
||||||
#: photologue/models.py:150
|
#: photologue/models.py:150
|
||||||
|
msgid "start date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: photologue/models.py:155
|
||||||
|
msgid "end date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: photologue/models.py:157
|
||||||
msgid "description"
|
msgid "description"
|
||||||
msgstr "descripción"
|
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"
|
msgid "is public"
|
||||||
msgstr "es público"
|
msgstr "es público"
|
||||||
|
|
||||||
#: photologue/models.py:154
|
#: photologue/models.py:167
|
||||||
msgid "Public galleries will be displayed in the default views."
|
msgid "Public galleries will be displayed in the default views."
|
||||||
msgstr "Las galerías públicas serán mostradas en las vistas por defecto."
|
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"
|
msgid "photos"
|
||||||
msgstr "fotos"
|
msgstr "fotos"
|
||||||
|
|
||||||
#: photologue/models.py:166
|
#: photologue/models.py:177
|
||||||
msgid "gallery"
|
msgid "gallery"
|
||||||
msgstr "galería"
|
msgstr "galería"
|
||||||
|
|
||||||
#: photologue/models.py:167
|
#: photologue/models.py:178
|
||||||
msgid "galleries"
|
msgid "galleries"
|
||||||
msgstr "galerías"
|
msgstr "galerías"
|
||||||
|
|
||||||
#: photologue/models.py:202
|
#: photologue/models.py:213
|
||||||
msgid "count"
|
msgid "count"
|
||||||
msgstr "contar"
|
msgstr "contar"
|
||||||
|
|
||||||
#: photologue/models.py:210
|
#: photologue/models.py:221
|
||||||
msgid "image"
|
msgid "image"
|
||||||
msgstr "imagen"
|
msgstr "imagen"
|
||||||
|
|
||||||
#: photologue/models.py:213
|
#: photologue/models.py:224
|
||||||
msgid "date taken"
|
msgid "date taken"
|
||||||
msgstr "fecha en la que se tomó"
|
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."
|
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."
|
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"
|
msgid "view count"
|
||||||
msgstr "Contador de visitas"
|
msgstr "Contador de visitas"
|
||||||
|
|
||||||
#: photologue/models.py:220
|
#: photologue/models.py:231
|
||||||
msgid "crop from"
|
msgid "crop from"
|
||||||
msgstr "Recortar desde"
|
msgstr "Recortar desde"
|
||||||
|
|
||||||
#: photologue/models.py:243
|
#: photologue/models.py:254
|
||||||
msgid "An \"admin_thumbnail\" photo size has not been defined."
|
msgid "An \"admin_thumbnail\" photo size has not been defined."
|
||||||
msgstr "El tamaño de foto de \"miniatura de admin\" no ha sido definido."
|
msgstr "El tamaño de foto de \"miniatura de admin\" no ha sido definido."
|
||||||
|
|
||||||
#: photologue/models.py:250
|
#: photologue/models.py:261
|
||||||
msgid "Thumbnail"
|
msgid "Thumbnail"
|
||||||
msgstr "Miniatura"
|
msgstr "Miniatura"
|
||||||
|
|
||||||
#: photologue/models.py:477
|
#: photologue/models.py:488 photologue/models.py:696
|
||||||
msgid "slug"
|
msgid "slug"
|
||||||
msgstr "slug"
|
msgstr "slug"
|
||||||
|
|
||||||
#: photologue/models.py:481
|
#: photologue/models.py:492
|
||||||
msgid "caption"
|
msgid "caption"
|
||||||
msgstr "pie de foto"
|
msgstr "pie de foto"
|
||||||
|
|
||||||
#: photologue/models.py:483
|
#: photologue/models.py:494
|
||||||
msgid "date added"
|
msgid "date added"
|
||||||
msgstr "fecha añadida"
|
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."
|
msgid "Public photographs will be displayed in the default views."
|
||||||
msgstr "Las fotos públicas serán mostradas en las vistas por defecto."
|
msgstr "Las fotos públicas serán mostradas en las vistas por defecto."
|
||||||
|
|
||||||
#: photologue/models.py:494
|
#: photologue/models.py:513
|
||||||
msgid "photo"
|
msgid "photo"
|
||||||
msgstr "foto"
|
msgstr "foto"
|
||||||
|
|
||||||
#: photologue/models.py:556
|
#: photologue/models.py:575 photologue/models.py:691
|
||||||
msgid "name"
|
msgid "name"
|
||||||
msgstr "nombre"
|
msgstr "nombre"
|
||||||
|
|
||||||
#: photologue/models.py:560
|
#: photologue/models.py:579
|
||||||
msgid ""
|
msgid ""
|
||||||
"Photo size name should contain only letters, numbers and underscores. "
|
"Photo size name should contain only letters, numbers and underscores. "
|
||||||
"Examples: \"thumbnail\", \"display\", \"small\", \"main_page_widget\"."
|
"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 "
|
"El nombre del tamaño solo puede contener letras, números y subrayados. Por "
|
||||||
"ejemplo:\"miniaturas\", \"muestra\", \"muestra_principal\"."
|
"ejemplo:\"miniaturas\", \"muestra\", \"muestra_principal\"."
|
||||||
|
|
||||||
#: photologue/models.py:567
|
#: photologue/models.py:586
|
||||||
msgid "width"
|
msgid "width"
|
||||||
msgstr "anchura"
|
msgstr "anchura"
|
||||||
|
|
||||||
#: photologue/models.py:570
|
#: photologue/models.py:589
|
||||||
msgid ""
|
msgid ""
|
||||||
"If width is set to \"0\" the image will be scaled to the supplied height."
|
"If width is set to \"0\" the image will be scaled to the supplied height."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Si la anchura se establece a \"0\" la imagen será escalada hasta la altura "
|
"Si la anchura se establece a \"0\" la imagen será escalada hasta la altura "
|
||||||
"proporcionada"
|
"proporcionada"
|
||||||
|
|
||||||
#: photologue/models.py:571
|
#: photologue/models.py:590
|
||||||
msgid "height"
|
msgid "height"
|
||||||
msgstr "altura"
|
msgstr "altura"
|
||||||
|
|
||||||
#: photologue/models.py:574
|
#: photologue/models.py:593
|
||||||
msgid ""
|
msgid ""
|
||||||
"If height is set to \"0\" the image will be scaled to the supplied width"
|
"If height is set to \"0\" the image will be scaled to the supplied width"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Si la altura se establece a \"0\" la imagen será escalada hasta la anchura "
|
"Si la altura se establece a \"0\" la imagen será escalada hasta la anchura "
|
||||||
"proporcionada"
|
"proporcionada"
|
||||||
|
|
||||||
#: photologue/models.py:575
|
#: photologue/models.py:594
|
||||||
msgid "quality"
|
msgid "quality"
|
||||||
msgstr "calidad"
|
msgstr "calidad"
|
||||||
|
|
||||||
#: photologue/models.py:578
|
#: photologue/models.py:597
|
||||||
msgid "JPEG image quality."
|
msgid "JPEG image quality."
|
||||||
msgstr "Calidad de imagen JPEG."
|
msgstr "Calidad de imagen JPEG."
|
||||||
|
|
||||||
#: photologue/models.py:579
|
#: photologue/models.py:598
|
||||||
msgid "upscale images?"
|
msgid "upscale images?"
|
||||||
msgstr "¿Aumentar imágenes?"
|
msgstr "¿Aumentar imágenes?"
|
||||||
|
|
||||||
#: photologue/models.py:581
|
#: photologue/models.py:600
|
||||||
msgid ""
|
msgid ""
|
||||||
"If selected the image will be scaled up if necessary to fit the supplied "
|
"If selected the image will be scaled up if necessary to fit the supplied "
|
||||||
"dimensions. Cropped sizes will be upscaled regardless of this setting."
|
"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 "
|
"las dimensiones proporcionadas. Los tamaños recortados serán aumentados de "
|
||||||
"acuerdo a esta opción."
|
"acuerdo a esta opción."
|
||||||
|
|
||||||
#: photologue/models.py:585
|
#: photologue/models.py:604
|
||||||
msgid "crop to fit?"
|
msgid "crop to fit?"
|
||||||
msgstr "¿Recortar hasta ajustar?"
|
msgstr "¿Recortar hasta ajustar?"
|
||||||
|
|
||||||
#: photologue/models.py:587
|
#: photologue/models.py:606
|
||||||
msgid ""
|
msgid ""
|
||||||
"If selected the image will be scaled and cropped to fit the supplied "
|
"If selected the image will be scaled and cropped to fit the supplied "
|
||||||
"dimensions."
|
"dimensions."
|
||||||
|
|
@ -261,21 +281,21 @@ msgstr ""
|
||||||
"Si se selecciona la imagen será escalada y recortada para ajustarse a las "
|
"Si se selecciona la imagen será escalada y recortada para ajustarse a las "
|
||||||
"dimensiones proporcionadas."
|
"dimensiones proporcionadas."
|
||||||
|
|
||||||
#: photologue/models.py:589
|
#: photologue/models.py:608
|
||||||
msgid "pre-cache?"
|
msgid "pre-cache?"
|
||||||
msgstr "¿pre-cachear?"
|
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."
|
msgid "If selected this photo size will be pre-cached as photos are added."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Si se selecciona, este tamaño de foto será pre-cacheado cuando se añadan "
|
"Si se selecciona, este tamaño de foto será pre-cacheado cuando se añadan "
|
||||||
"nuevas fotos."
|
"nuevas fotos."
|
||||||
|
|
||||||
#: photologue/models.py:592
|
#: photologue/models.py:611
|
||||||
msgid "increment view count?"
|
msgid "increment view count?"
|
||||||
msgstr "¿incrementar contador de visualizaciones?"
|
msgstr "¿incrementar contador de visualizaciones?"
|
||||||
|
|
||||||
#: photologue/models.py:594
|
#: photologue/models.py:613
|
||||||
msgid ""
|
msgid ""
|
||||||
"If selected the image's \"view_count\" will be incremented when this photo "
|
"If selected the image's \"view_count\" will be incremented when this photo "
|
||||||
"size is displayed."
|
"size is displayed."
|
||||||
|
|
@ -283,31 +303,31 @@ msgstr ""
|
||||||
"Si se selecciona el \"contador de visualizaciones\" se incrementará cuando "
|
"Si se selecciona el \"contador de visualizaciones\" se incrementará cuando "
|
||||||
"esta foto sea visualizada."
|
"esta foto sea visualizada."
|
||||||
|
|
||||||
#: photologue/models.py:599
|
#: photologue/models.py:618
|
||||||
msgid "photo size"
|
msgid "photo size"
|
||||||
msgstr "tamaño de foto"
|
msgstr "tamaño de foto"
|
||||||
|
|
||||||
#: photologue/models.py:600
|
#: photologue/models.py:619
|
||||||
msgid "photo sizes"
|
msgid "photo sizes"
|
||||||
msgstr "tamaños de foto"
|
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."
|
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."
|
msgstr "Solo puede recortar las fotos si ancho y alto están establecidos."
|
||||||
|
|
||||||
#: photologue_custom/admin.py:43 photologue_custom/models.py:51
|
#: photologue/models.py:702
|
||||||
msgid "owner"
|
msgid "tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:34
|
#: photologue_custom/forms.py:22
|
||||||
msgid "Gallery"
|
msgid "Gallery"
|
||||||
msgstr "Galería"
|
msgstr "Galería"
|
||||||
|
|
||||||
#: photologue_custom/forms.py:36
|
#: photologue_custom/forms.py:24
|
||||||
msgid "-- Create a new gallery --"
|
msgid "-- Create a new gallery --"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:37
|
#: photologue_custom/forms.py:25
|
||||||
msgid ""
|
msgid ""
|
||||||
"Select a gallery to add these images to. Leave this empty to create a new "
|
"Select a gallery to add these images to. Leave this empty to create a new "
|
||||||
"gallery from the supplied title."
|
"gallery from the supplied title."
|
||||||
|
|
@ -315,58 +335,42 @@ msgstr ""
|
||||||
"Seleccione una galería para agregarle estas imágenes. Déjelo vacío para "
|
"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."
|
"crear una nueva galería a partir de este título."
|
||||||
|
|
||||||
#: photologue_custom/forms.py:41
|
#: photologue_custom/forms.py:29
|
||||||
#, fuzzy
|
|
||||||
#| msgid "View all galleries"
|
|
||||||
msgid "New gallery title"
|
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"
|
msgid "New gallery event start date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:51
|
#: photologue_custom/forms.py:39
|
||||||
msgid "New gallery event end date"
|
msgid "New gallery event end date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:57
|
#: photologue_custom/forms.py:45
|
||||||
#, fuzzy
|
|
||||||
#| msgid "gallery"
|
|
||||||
msgid "New gallery tags"
|
msgid "New gallery tags"
|
||||||
msgstr "galería"
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:59
|
#: photologue_custom/forms.py:47
|
||||||
msgid ""
|
msgid ""
|
||||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:76
|
#: photologue_custom/forms.py:64
|
||||||
#: photologue_custom/templates/photologue/upload.html:6
|
#: photologue_custom/templates/photologue/upload.html:6
|
||||||
#: photologue_custom/templates/photologue/upload.html:73
|
#: photologue_custom/templates/photologue/upload.html:73
|
||||||
msgid "Upload"
|
msgid "Upload"
|
||||||
msgstr "Subir"
|
msgstr "Subir"
|
||||||
|
|
||||||
#: photologue_custom/forms.py:82
|
#: photologue_custom/forms.py:70
|
||||||
msgid "A gallery with that title already exists."
|
msgid "A gallery with that title already exists."
|
||||||
msgstr "Ya existe una galería con ese título."
|
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."
|
msgid "Select an existing gallery, or enter a title for a new gallery."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Seleccione una galería existente o ingrese un nuevo nombre para la galería."
|
"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:7
|
||||||
#: photologue_custom/templates/photologue/gallery_archive.html:12
|
#: photologue_custom/templates/photologue/gallery_archive.html:12
|
||||||
msgid "Latest photo galleries"
|
msgid "Latest photo galleries"
|
||||||
|
|
@ -399,16 +403,12 @@ msgid "to"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/templates/photologue/gallery_detail.html:57
|
#: photologue_custom/templates/photologue/gallery_detail.html:57
|
||||||
#, fuzzy
|
|
||||||
#| msgid "All photos"
|
|
||||||
msgid "All pictures"
|
msgid "All pictures"
|
||||||
msgstr "Todas las fotos"
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/templates/photologue/gallery_detail.html:78
|
#: photologue_custom/templates/photologue/gallery_detail.html:78
|
||||||
#, fuzzy
|
|
||||||
#| msgid "View all galleries"
|
|
||||||
msgid "Download all gallery"
|
msgid "Download all gallery"
|
||||||
msgstr "Ver todas las galerías"
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/templates/photologue/photo_detail.html:13
|
#: photologue_custom/templates/photologue/photo_detail.html:13
|
||||||
msgid "Published"
|
msgid "Published"
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Photologue\n"
|
"Project-Id-Version: Photologue\n"
|
||||||
"Report-Msgid-Bugs-To: \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"
|
"PO-Revision-Date: 2017-12-03 14:47+0000\n"
|
||||||
"Last-Translator: Richard Barran <richard@arbee-design.co.uk>\n"
|
"Last-Translator: Richard Barran <richard@arbee-design.co.uk>\n"
|
||||||
"Language-Team: French (http://www.transifex.com/richardbarran/django-"
|
"Language-Team: French (http://www.transifex.com/richardbarran/django-"
|
||||||
|
|
@ -21,75 +21,131 @@ msgstr ""
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\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"
|
msgid "Very Low"
|
||||||
msgstr "Très Bas"
|
msgstr "Très Bas"
|
||||||
|
|
||||||
#: photologue/models.py:87
|
#: photologue/models.py:85
|
||||||
msgid "Low"
|
msgid "Low"
|
||||||
msgstr "Bas"
|
msgstr "Bas"
|
||||||
|
|
||||||
#: photologue/models.py:88
|
#: photologue/models.py:86
|
||||||
msgid "Medium-Low"
|
msgid "Medium-Low"
|
||||||
msgstr "Moyen-Bas"
|
msgstr "Moyen-Bas"
|
||||||
|
|
||||||
#: photologue/models.py:89
|
#: photologue/models.py:87
|
||||||
msgid "Medium"
|
msgid "Medium"
|
||||||
msgstr "Moyen"
|
msgstr "Moyen"
|
||||||
|
|
||||||
#: photologue/models.py:90
|
#: photologue/models.py:88
|
||||||
msgid "Medium-High"
|
msgid "Medium-High"
|
||||||
msgstr "Moyen-Haut"
|
msgstr "Moyen-Haut"
|
||||||
|
|
||||||
#: photologue/models.py:91
|
#: photologue/models.py:89
|
||||||
msgid "High"
|
msgid "High"
|
||||||
msgstr "Haut"
|
msgstr "Haut"
|
||||||
|
|
||||||
#: photologue/models.py:92
|
#: photologue/models.py:90
|
||||||
msgid "Very High"
|
msgid "Very High"
|
||||||
msgstr "Très Haut"
|
msgstr "Très Haut"
|
||||||
|
|
||||||
#: photologue/models.py:97
|
#: photologue/models.py:95
|
||||||
msgid "Top"
|
msgid "Top"
|
||||||
msgstr "Sommet"
|
msgstr "Sommet"
|
||||||
|
|
||||||
#: photologue/models.py:98
|
#: photologue/models.py:96
|
||||||
msgid "Right"
|
msgid "Right"
|
||||||
msgstr "Droite"
|
msgstr "Droite"
|
||||||
|
|
||||||
#: photologue/models.py:99
|
#: photologue/models.py:97
|
||||||
msgid "Bottom"
|
msgid "Bottom"
|
||||||
msgstr "Bas"
|
msgstr "Bas"
|
||||||
|
|
||||||
#: photologue/models.py:100
|
#: photologue/models.py:98
|
||||||
msgid "Left"
|
msgid "Left"
|
||||||
msgstr "Gauche"
|
msgstr "Gauche"
|
||||||
|
|
||||||
#: photologue/models.py:101
|
#: photologue/models.py:99
|
||||||
msgid "Center (Default)"
|
msgid "Center (Default)"
|
||||||
msgstr "Centré (par défaut)"
|
msgstr "Centré (par défaut)"
|
||||||
|
|
||||||
#: photologue/models.py:105
|
#: photologue/models.py:103
|
||||||
msgid "Flip left to right"
|
msgid "Flip left to right"
|
||||||
msgstr "Inversion de gauche à droite"
|
msgstr "Inversion de gauche à droite"
|
||||||
|
|
||||||
#: photologue/models.py:106
|
#: photologue/models.py:104
|
||||||
msgid "Flip top to bottom"
|
msgid "Flip top to bottom"
|
||||||
msgstr "Inversion de haut en bas"
|
msgstr "Inversion de haut en bas"
|
||||||
|
|
||||||
#: photologue/models.py:107
|
#: photologue/models.py:105
|
||||||
msgid "Rotate 90 degrees counter-clockwise"
|
msgid "Rotate 90 degrees counter-clockwise"
|
||||||
msgstr "Rotation de 90 degrés dans le sens anti-horloger"
|
msgstr "Rotation de 90 degrés dans le sens anti-horloger"
|
||||||
|
|
||||||
#: photologue/models.py:108
|
#: photologue/models.py:106
|
||||||
msgid "Rotate 90 degrees clockwise"
|
msgid "Rotate 90 degrees clockwise"
|
||||||
msgstr "Rotation de 90 degrés dans le sens horloger"
|
msgstr "Rotation de 90 degrés dans le sens horloger"
|
||||||
|
|
||||||
#: photologue/models.py:109
|
#: photologue/models.py:107
|
||||||
msgid "Rotate 180 degrees"
|
msgid "Rotate 180 degrees"
|
||||||
msgstr "Rotation de 180 degrés"
|
msgstr "Rotation de 180 degrés"
|
||||||
|
|
||||||
#: photologue/models.py:119
|
#: photologue/models.py:117
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Chain multiple filters using the following pattern \"FILTER_ONE->FILTER_TWO-"
|
"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 "
|
">FILTRE_DEUX->FILTRE_TROIS\". Les filtres d'image seront appliqués dans "
|
||||||
"l'ordre. Les filtres suivants sont disponibles: %s."
|
"l'ordre. Les filtres suivants sont disponibles: %s."
|
||||||
|
|
||||||
#: photologue/models.py:141
|
#: photologue/models.py:139
|
||||||
msgid "date published"
|
msgid "date published"
|
||||||
msgstr "date de publication"
|
msgstr "date de publication"
|
||||||
|
|
||||||
#: photologue/models.py:143 photologue/models.py:474
|
#: photologue/models.py:141 photologue/models.py:485
|
||||||
msgid "title"
|
msgid "title"
|
||||||
msgstr "titre"
|
msgstr "titre"
|
||||||
|
|
||||||
#: photologue/models.py:146
|
#: photologue/models.py:144
|
||||||
msgid "title slug"
|
msgid "title slug"
|
||||||
msgstr "version abrégée du titre"
|
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."
|
msgid "A \"slug\" is a unique URL-friendly title for an object."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Un \"slug\" est un titre abrégé et unique, compatible avec les URL, pour un "
|
"Un \"slug\" est un titre abrégé et unique, compatible avec les URL, pour un "
|
||||||
"objet."
|
"objet."
|
||||||
|
|
||||||
#: photologue/models.py:150
|
#: 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"
|
msgid "description"
|
||||||
msgstr "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"
|
msgid "is public"
|
||||||
msgstr "est public"
|
msgstr "est public"
|
||||||
|
|
||||||
#: photologue/models.py:154
|
#: photologue/models.py:167
|
||||||
msgid "Public galleries will be displayed in the default views."
|
msgid "Public galleries will be displayed in the default views."
|
||||||
msgstr "Les galeries publiques seront affichée dans les vues par défaut."
|
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"
|
msgid "photos"
|
||||||
msgstr "photos"
|
msgstr "photos"
|
||||||
|
|
||||||
#: photologue/models.py:166
|
#: photologue/models.py:177
|
||||||
msgid "gallery"
|
msgid "gallery"
|
||||||
msgstr "galerie"
|
msgstr "galerie"
|
||||||
|
|
||||||
#: photologue/models.py:167
|
#: photologue/models.py:178
|
||||||
msgid "galleries"
|
msgid "galleries"
|
||||||
msgstr "galleries"
|
msgstr "galleries"
|
||||||
|
|
||||||
#: photologue/models.py:202
|
#: photologue/models.py:213
|
||||||
msgid "count"
|
msgid "count"
|
||||||
msgstr "nombre"
|
msgstr "nombre"
|
||||||
|
|
||||||
#: photologue/models.py:210
|
#: photologue/models.py:221
|
||||||
msgid "image"
|
msgid "image"
|
||||||
msgstr "image"
|
msgstr "image"
|
||||||
|
|
||||||
#: photologue/models.py:213
|
#: photologue/models.py:224
|
||||||
msgid "date taken"
|
msgid "date taken"
|
||||||
msgstr "date de prise de vue"
|
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."
|
msgid "Date image was taken; is obtained from the image EXIF data."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"La date à laquelle l'image a été prise ; obtenue à partir des données EXIF "
|
"La date à laquelle l'image a été prise ; obtenue à partir des données EXIF "
|
||||||
"de l'image."
|
"de l'image."
|
||||||
|
|
||||||
#: photologue/models.py:217
|
#: photologue/models.py:228
|
||||||
msgid "view count"
|
msgid "view count"
|
||||||
msgstr "nombre"
|
msgstr "nombre"
|
||||||
|
|
||||||
#: photologue/models.py:220
|
#: photologue/models.py:231
|
||||||
msgid "crop from"
|
msgid "crop from"
|
||||||
msgstr "découper à partir de"
|
msgstr "découper à partir de"
|
||||||
|
|
||||||
#: photologue/models.py:243
|
#: photologue/models.py:254
|
||||||
msgid "An \"admin_thumbnail\" photo size has not been defined."
|
msgid "An \"admin_thumbnail\" photo size has not been defined."
|
||||||
msgstr "Une taille de photo \"admin_thumbnail\" n'a pas encore été définie."
|
msgstr "Une taille de photo \"admin_thumbnail\" n'a pas encore été définie."
|
||||||
|
|
||||||
#: photologue/models.py:250
|
#: photologue/models.py:261
|
||||||
msgid "Thumbnail"
|
msgid "Thumbnail"
|
||||||
msgstr "Miniature"
|
msgstr "Miniature"
|
||||||
|
|
||||||
#: photologue/models.py:477
|
#: photologue/models.py:488 photologue/models.py:696
|
||||||
msgid "slug"
|
msgid "slug"
|
||||||
msgstr "libellé court"
|
msgstr "libellé court"
|
||||||
|
|
||||||
#: photologue/models.py:481
|
#: photologue/models.py:492
|
||||||
msgid "caption"
|
msgid "caption"
|
||||||
msgstr "légende"
|
msgstr "légende"
|
||||||
|
|
||||||
#: photologue/models.py:483
|
#: photologue/models.py:494
|
||||||
msgid "date added"
|
msgid "date added"
|
||||||
msgstr "date d'ajout"
|
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."
|
msgid "Public photographs will be displayed in the default views."
|
||||||
msgstr "Les photographies publique seront affichées dans les vues par défaut."
|
msgstr "Les photographies publique seront affichées dans les vues par défaut."
|
||||||
|
|
||||||
#: photologue/models.py:494
|
#: photologue/models.py:513
|
||||||
msgid "photo"
|
msgid "photo"
|
||||||
msgstr "photo"
|
msgstr "photo"
|
||||||
|
|
||||||
#: photologue/models.py:556
|
#: photologue/models.py:575 photologue/models.py:691
|
||||||
msgid "name"
|
msgid "name"
|
||||||
msgstr "nom"
|
msgstr "nom"
|
||||||
|
|
||||||
#: photologue/models.py:560
|
#: photologue/models.py:579
|
||||||
msgid ""
|
msgid ""
|
||||||
"Photo size name should contain only letters, numbers and underscores. "
|
"Photo size name should contain only letters, numbers and underscores. "
|
||||||
"Examples: \"thumbnail\", \"display\", \"small\", \"main_page_widget\"."
|
"Examples: \"thumbnail\", \"display\", \"small\", \"main_page_widget\"."
|
||||||
|
|
@ -209,41 +281,41 @@ msgstr ""
|
||||||
"chiffres et des caractères de soulignement. Exemples: \"miniature\", "
|
"chiffres et des caractères de soulignement. Exemples: \"miniature\", "
|
||||||
"\"affichage\", \"petit\", \"widget_page_principale\"."
|
"\"affichage\", \"petit\", \"widget_page_principale\"."
|
||||||
|
|
||||||
#: photologue/models.py:567
|
#: photologue/models.py:586
|
||||||
msgid "width"
|
msgid "width"
|
||||||
msgstr "largeur"
|
msgstr "largeur"
|
||||||
|
|
||||||
#: photologue/models.py:570
|
#: photologue/models.py:589
|
||||||
msgid ""
|
msgid ""
|
||||||
"If width is set to \"0\" the image will be scaled to the supplied height."
|
"If width is set to \"0\" the image will be scaled to the supplied height."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Si la largeur est réglée à \"0\" l l'image sera redimensionnée par rapport à "
|
"Si la largeur est réglée à \"0\" l l'image sera redimensionnée par rapport à "
|
||||||
"la hauteur fournie."
|
"la hauteur fournie."
|
||||||
|
|
||||||
#: photologue/models.py:571
|
#: photologue/models.py:590
|
||||||
msgid "height"
|
msgid "height"
|
||||||
msgstr "hauteur"
|
msgstr "hauteur"
|
||||||
|
|
||||||
#: photologue/models.py:574
|
#: photologue/models.py:593
|
||||||
msgid ""
|
msgid ""
|
||||||
"If height is set to \"0\" the image will be scaled to the supplied width"
|
"If height is set to \"0\" the image will be scaled to the supplied width"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Si la hauteur est réglée à \"0\" l l'image sera redimensionnée par rapport à "
|
"Si la hauteur est réglée à \"0\" l l'image sera redimensionnée par rapport à "
|
||||||
"la largeur fournie."
|
"la largeur fournie."
|
||||||
|
|
||||||
#: photologue/models.py:575
|
#: photologue/models.py:594
|
||||||
msgid "quality"
|
msgid "quality"
|
||||||
msgstr "qualité"
|
msgstr "qualité"
|
||||||
|
|
||||||
#: photologue/models.py:578
|
#: photologue/models.py:597
|
||||||
msgid "JPEG image quality."
|
msgid "JPEG image quality."
|
||||||
msgstr "Qualité JPEG de l'image."
|
msgstr "Qualité JPEG de l'image."
|
||||||
|
|
||||||
#: photologue/models.py:579
|
#: photologue/models.py:598
|
||||||
msgid "upscale images?"
|
msgid "upscale images?"
|
||||||
msgstr "agrandir les images ?"
|
msgstr "agrandir les images ?"
|
||||||
|
|
||||||
#: photologue/models.py:581
|
#: photologue/models.py:600
|
||||||
msgid ""
|
msgid ""
|
||||||
"If selected the image will be scaled up if necessary to fit the supplied "
|
"If selected the image will be scaled up if necessary to fit the supplied "
|
||||||
"dimensions. Cropped sizes will be upscaled regardless of this setting."
|
"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 "
|
"dimensions fournies. Les dimensions ajustées seront agrandies sans prendre "
|
||||||
"en compte ce paramètre."
|
"en compte ce paramètre."
|
||||||
|
|
||||||
#: photologue/models.py:585
|
#: photologue/models.py:604
|
||||||
msgid "crop to fit?"
|
msgid "crop to fit?"
|
||||||
msgstr "découper pour adapter à la taille ?"
|
msgstr "découper pour adapter à la taille ?"
|
||||||
|
|
||||||
#: photologue/models.py:587
|
#: photologue/models.py:606
|
||||||
msgid ""
|
msgid ""
|
||||||
"If selected the image will be scaled and cropped to fit the supplied "
|
"If selected the image will be scaled and cropped to fit the supplied "
|
||||||
"dimensions."
|
"dimensions."
|
||||||
|
|
@ -264,21 +336,21 @@ msgstr ""
|
||||||
"Si sélectionné l'image sera redimensionnée et recadrée pour coïncider avec "
|
"Si sélectionné l'image sera redimensionnée et recadrée pour coïncider avec "
|
||||||
"les dimensions fournies."
|
"les dimensions fournies."
|
||||||
|
|
||||||
#: photologue/models.py:589
|
#: photologue/models.py:608
|
||||||
msgid "pre-cache?"
|
msgid "pre-cache?"
|
||||||
msgstr "mise en 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."
|
msgid "If selected this photo size will be pre-cached as photos are added."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Si sélectionné cette taille de photo sera mise en cache au moment au les "
|
"Si sélectionné cette taille de photo sera mise en cache au moment au les "
|
||||||
"photos sont ajoutées."
|
"photos sont ajoutées."
|
||||||
|
|
||||||
#: photologue/models.py:592
|
#: photologue/models.py:611
|
||||||
msgid "increment view count?"
|
msgid "increment view count?"
|
||||||
msgstr "incrémenter le nombre d'affichages ?"
|
msgstr "incrémenter le nombre d'affichages ?"
|
||||||
|
|
||||||
#: photologue/models.py:594
|
#: photologue/models.py:613
|
||||||
msgid ""
|
msgid ""
|
||||||
"If selected the image's \"view_count\" will be incremented when this photo "
|
"If selected the image's \"view_count\" will be incremented when this photo "
|
||||||
"size is displayed."
|
"size is displayed."
|
||||||
|
|
@ -286,148 +358,75 @@ msgstr ""
|
||||||
"Si sélectionné le \"view_count\" (nombre d'affichage) de l'image sera "
|
"Si sélectionné le \"view_count\" (nombre d'affichage) de l'image sera "
|
||||||
"incrémenté quand cette taille de photo sera affichée."
|
"incrémenté quand cette taille de photo sera affichée."
|
||||||
|
|
||||||
#: photologue/models.py:599
|
#: photologue/models.py:618
|
||||||
msgid "photo size"
|
msgid "photo size"
|
||||||
msgstr "taille de la photo"
|
msgstr "taille de la photo"
|
||||||
|
|
||||||
#: photologue/models.py:600
|
#: photologue/models.py:619
|
||||||
msgid "photo sizes"
|
msgid "photo sizes"
|
||||||
msgstr "tailles des photos"
|
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."
|
msgid "Can only crop photos if both width and height dimensions are set."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"La hauteur et la largeur doivent être toutes les deux définies pour "
|
"La hauteur et la largeur doivent être toutes les deux définies pour "
|
||||||
"retailler des photos."
|
"retailler des photos."
|
||||||
|
|
||||||
#: photologue_custom/admin.py:43 photologue_custom/models.py:51
|
#: photologue/models.py:702
|
||||||
msgid "owner"
|
msgid "tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: photologue_custom/forms.py:34
|
#: photologue/templates/photologue/gallery_archive.html:7
|
||||||
msgid "Gallery"
|
#: photologue/templates/photologue/gallery_archive.html:12
|
||||||
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."
|
|
||||||
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
|
|
||||||
msgid "Latest photo galleries"
|
msgid "Latest photo galleries"
|
||||||
msgstr "Dernières galeries de photos"
|
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"
|
msgid "Filter by year"
|
||||||
msgstr "Filtrer par année"
|
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"
|
msgid "No galleries were found"
|
||||||
msgstr "Aucune galerie trouvée"
|
msgstr "Aucune galerie trouvée"
|
||||||
|
|
||||||
#: photologue_custom/templates/photologue/gallery_archive_year.html:7
|
#: photologue/templates/photologue/gallery_archive_year.html:7
|
||||||
#: photologue_custom/templates/photologue/gallery_archive_year.html:12
|
#: photologue/templates/photologue/gallery_archive_year.html:12
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Galleries for %(show_year)s"
|
msgid "Galleries for %(show_year)s"
|
||||||
msgstr "Galeries de %(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"
|
msgid "View all galleries"
|
||||||
msgstr "Afficher toutes les galeries"
|
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."
|
msgid "No galleries were found."
|
||||||
msgstr "Aucune galerie trouvée."
|
msgstr "Aucune galerie trouvée."
|
||||||
|
|
||||||
#: photologue_custom/templates/photologue/gallery_detail.html:41
|
#: photologue/templates/photologue/gallery_detail.html:41
|
||||||
msgid "to"
|
msgid "to"
|
||||||
msgstr ""
|
msgstr "au"
|
||||||
|
|
||||||
#: photologue_custom/templates/photologue/gallery_detail.html:57
|
#: photologue/templates/photologue/gallery_detail.html:57
|
||||||
#, fuzzy
|
|
||||||
#| msgid "All photos"
|
|
||||||
msgid "All pictures"
|
msgid "All pictures"
|
||||||
msgstr "Toutes les photos"
|
msgstr "Toutes les photos"
|
||||||
|
|
||||||
#: photologue_custom/templates/photologue/gallery_detail.html:78
|
#: photologue/templates/photologue/gallery_detail.html:78
|
||||||
#, fuzzy
|
|
||||||
#| msgid "View all galleries"
|
|
||||||
msgid "Download all gallery"
|
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"
|
msgid "Published"
|
||||||
msgstr "Publiée le"
|
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"
|
msgid "This photo is found in the following galleries"
|
||||||
msgstr "Cette photo se trouve dans les galeries suivantes"
|
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"
|
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"
|
msgid "Owner will be"
|
||||||
msgstr ""
|
msgstr "Le propriétaire sera"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
|
import hashlib
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
from photologue.models import Gallery
|
from photologue.models import Gallery
|
||||||
|
|
||||||
import hashlib
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = 'List all duplicate for chosen galleries'
|
help = 'List all duplicate for chosen galleries'
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
from pathlib import Path
|
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from photologue.models import Gallery
|
from photologue.models import Gallery
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
|
|
@ -16,7 +16,7 @@ class Command(BaseCommand):
|
||||||
media_dir = Path(settings.MEDIA_ROOT)
|
media_dir = Path(settings.MEDIA_ROOT)
|
||||||
for gallery in Gallery.objects.all():
|
for gallery in Gallery.objects.all():
|
||||||
# Create gallery directory
|
# Create gallery directory
|
||||||
gallery_year = str(gallery.extended.date_start.year)
|
gallery_year = str(gallery.date_start.year)
|
||||||
gallery_dir = Path('photos') / gallery_year / gallery.slug
|
gallery_dir = Path('photos') / gallery_year / gallery.slug
|
||||||
gallery_path = media_dir / gallery_dir
|
gallery_path = media_dir / gallery_dir
|
||||||
if not gallery_path.exists():
|
if not gallery_path.exists():
|
||||||
|
|
@ -1,158 +1,96 @@
|
||||||
# -*- coding: utf-8 -*-
|
# Generated by Django 3.2.11 on 2022-01-30 10:14
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
import django.core.validators
|
import django.core.validators
|
||||||
import django.utils.timezone
|
|
||||||
import sortedm2m.fields
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
import photologue.models
|
import photologue.models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('sites', '0001_initial'),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Gallery',
|
name='PhotoSize',
|
||||||
fields=[
|
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')),
|
||||||
('date_added', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date published')),
|
('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')),
|
||||||
('title', models.CharField(max_length=50, verbose_name='title', unique=True)),
|
('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')),
|
||||||
('slug', models.SlugField(help_text='A "slug" is a unique URL-friendly title for an object.', verbose_name='title slug', unique=True)),
|
('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')),
|
||||||
('description', models.TextField(blank=True, verbose_name='description')),
|
('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')),
|
||||||
('is_public', models.BooleanField(help_text='Public galleries will be displayed in the default views.', verbose_name='is public', default=True)),
|
('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?')),
|
||||||
('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')),
|
('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?')),
|
||||||
('sites', models.ManyToManyField(blank=True, verbose_name='sites', null=True, to='sites.Site')),
|
('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={
|
options={
|
||||||
'get_latest_by': 'date_added',
|
'verbose_name': 'photo size',
|
||||||
'verbose_name': 'gallery',
|
'verbose_name_plural': 'photo sizes',
|
||||||
'ordering': ['-date_added'],
|
'ordering': ['width', 'height'],
|
||||||
'verbose_name_plural': 'galleries',
|
|
||||||
},
|
},
|
||||||
bases=(models.Model,),
|
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='GalleryUpload',
|
name='Tag',
|
||||||
fields=[
|
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')),
|
||||||
('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')),
|
('name', models.CharField(max_length=250, unique=True, verbose_name='name')),
|
||||||
('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')),
|
('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(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)),
|
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'gallery upload',
|
'verbose_name': 'tag',
|
||||||
'verbose_name_plural': 'gallery uploads',
|
'verbose_name_plural': 'tags',
|
||||||
|
'ordering': ['name'],
|
||||||
},
|
},
|
||||||
bases=(models.Model,),
|
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Photo',
|
name='Photo',
|
||||||
fields=[
|
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')),
|
('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)),
|
('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(verbose_name='view count', default=0, editable=False)),
|
('view_count', models.PositiveIntegerField(default=0, editable=False, verbose_name='view count')),
|
||||||
('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)')])),
|
('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=50, verbose_name='title', unique=True)),
|
('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.', verbose_name='slug', unique=True)),
|
('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')),
|
('caption', models.TextField(blank=True, verbose_name='caption')),
|
||||||
('date_added', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date added')),
|
('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)),
|
('license', models.CharField(blank=True, max_length=255, verbose_name='license')),
|
||||||
('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')),
|
('is_public', models.BooleanField(default=True, help_text='Public photographs will be displayed in the default views.', verbose_name='is public')),
|
||||||
('sites', models.ManyToManyField(blank=True, verbose_name='sites', null=True, to='sites.Site')),
|
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='owner')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'get_latest_by': 'date_added',
|
|
||||||
'verbose_name': 'photo',
|
'verbose_name': 'photo',
|
||||||
'ordering': ['-date_added'],
|
|
||||||
'verbose_name_plural': 'photos',
|
'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(
|
migrations.CreateModel(
|
||||||
name='PhotoEffect',
|
name='Gallery',
|
||||||
fields=[
|
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')),
|
||||||
('name', models.CharField(max_length=30, verbose_name='name', unique=True)),
|
('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')),
|
('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')])),
|
('is_public', models.BooleanField(default=True, help_text='Public galleries will be displayed in the default views.', verbose_name='is public')),
|
||||||
('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)),
|
('photos', models.ManyToManyField(blank=True, related_name='galleries', to='photologue.Photo', verbose_name='photos')),
|
||||||
('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)),
|
('tags', models.ManyToManyField(blank=True, related_name='galleries', to='photologue.Tag', verbose_name='tags')),
|
||||||
('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={
|
options={
|
||||||
'verbose_name': 'photo effect',
|
'verbose_name': 'gallery',
|
||||||
'verbose_name_plural': 'photo effects',
|
'verbose_name_plural': 'galleries',
|
||||||
|
'ordering': ['-date_added'],
|
||||||
|
'get_latest_by': 'date_added',
|
||||||
},
|
},
|
||||||
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',
|
|
||||||
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')),
|
|
||||||
('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)),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'watermark',
|
|
||||||
'verbose_name_plural': 'watermarks',
|
|
||||||
},
|
|
||||||
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,
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
21
photologue/migrations/0002_auto_20220130_1020.py
Normal file
21
photologue/migrations/0002_auto_20220130_1020.py
Normal file
|
|
@ -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',
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -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),
|
|
||||||
]
|
|
||||||
|
|
@ -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),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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',
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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',
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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',
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -136,8 +136,6 @@ class TagField(models.CharField):
|
||||||
|
|
||||||
|
|
||||||
class Gallery(models.Model):
|
class Gallery(models.Model):
|
||||||
date_added = models.DateTimeField(_('date published'),
|
|
||||||
default=now)
|
|
||||||
title = models.CharField(_('title'),
|
title = models.CharField(_('title'),
|
||||||
max_length=250,
|
max_length=250,
|
||||||
unique=True)
|
unique=True)
|
||||||
|
|
@ -145,8 +143,23 @@ class Gallery(models.Model):
|
||||||
unique=True,
|
unique=True,
|
||||||
max_length=250,
|
max_length=250,
|
||||||
help_text=_('A "slug" is a unique URL-friendly title for an object.'))
|
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'),
|
description = models.TextField(_('description'),
|
||||||
blank=True)
|
blank=True)
|
||||||
|
tags = models.ManyToManyField(
|
||||||
|
'photologue.Tag',
|
||||||
|
related_name='galleries',
|
||||||
|
verbose_name=_('tags'),
|
||||||
|
blank=True,
|
||||||
|
)
|
||||||
is_public = models.BooleanField(_('is public'),
|
is_public = models.BooleanField(_('is public'),
|
||||||
default=True,
|
default=True,
|
||||||
help_text=_('Public galleries will be displayed '
|
help_text=_('Public galleries will be displayed '
|
||||||
|
|
@ -157,13 +170,13 @@ class Gallery(models.Model):
|
||||||
blank=True)
|
blank=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['-date_added']
|
ordering = ['-date_start']
|
||||||
get_latest_by = 'date_added'
|
get_latest_by = 'date_start'
|
||||||
verbose_name = _('gallery')
|
verbose_name = _('gallery')
|
||||||
verbose_name_plural = _('galleries')
|
verbose_name_plural = _('galleries')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.title
|
return f"{ self.title } ({self.date_start})"
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('photologue:pl-gallery', args=[self.slug])
|
return reverse('photologue:pl-gallery', args=[self.slug])
|
||||||
|
|
@ -478,6 +491,16 @@ class Photo(ImageModel):
|
||||||
blank=True)
|
blank=True)
|
||||||
date_added = models.DateTimeField(_('date added'),
|
date_added = models.DateTimeField(_('date added'),
|
||||||
default=now)
|
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'),
|
is_public = models.BooleanField(_('is public'),
|
||||||
default=True,
|
default=True,
|
||||||
help_text=_('Public photographs will be displayed in the default views.'))
|
help_text=_('Public photographs will be displayed in the default views.'))
|
||||||
|
|
@ -657,3 +680,25 @@ def init_size_method_map():
|
||||||
{'base_name': '_get_size_url', 'size': size}
|
{'base_name': '_get_size_url', 'size': size}
|
||||||
size_method_map['get_%s_filename' % size] = \
|
size_method_map['get_%s_filename' % size] = \
|
||||||
{'base_name': '_get_size_filename', 'size': 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
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
|
@ -38,10 +38,10 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h1>
|
</h1>
|
||||||
{% if gallery.extended.date_start %}<p class="text-muted small">{{ gallery.extended.date_start }}{% if gallery.extended.date_end and gallery.extended.date_end != gallery.extended.date_start %} {% trans "to" %} {{ gallery.extended.date_end }}{% endif %}</p>{% endif %}
|
{% if gallery.date_start %}<p class="text-muted small">{{ gallery.date_start }}{% if gallery.date_end and gallery.date_end != gallery.date_start %} {% trans "to" %} {{ gallery.date_end }}{% endif %}</p>{% endif %}
|
||||||
{% if gallery.extended.tags.all %}
|
{% if gallery.tags.all %}
|
||||||
<p class="text-muted">
|
<p class="text-muted">
|
||||||
Tags : {% for tag in gallery.extended.tags.all %}
|
Tags : {% for tag in gallery.tags.all %}
|
||||||
<a class="badge rounded-pill bg-dark text-decoration-none" href="{% url 'photologue:tag-detail' tag.slug %}">{{ tag }}</a>
|
<a class="badge rounded-pill bg-dark text-decoration-none" href="{% url 'photologue:tag-detail' tag.slug %}">{{ tag }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -70,7 +70,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
<div class="card-body row" id="lightgallery">
|
<div class="card-body row" id="lightgallery">
|
||||||
{% for photo in photos %}
|
{% for photo in photos %}
|
||||||
<a class="col-6 col-md-3 mb-2 text-center" href="{{ photo.get_absolute_url }}" data-src="{{ photo.get_display_url }}" data-download-url="{{ photo.image.url }}" data-slide-name="{{ photo.id }}">
|
<a class="col-6 col-md-3 mb-2 text-center" href="{{ photo.get_absolute_url }}" data-src="{{ photo.get_display_url }}" data-download-url="{{ photo.image.url }}" data-slide-name="{{ photo.id }}">
|
||||||
<img src="{{ photo.get_thumbnail_url }}" loading="lazy" class="img-thumbnail" alt="{{ photo.title }}{% if photo.date_taken %} - {{ photo.date_taken|date }} {{ photo.date_taken|time }}{% endif %} - {{ photo.extended.owner.get_full_name }}{% if photo.extended.license %} - {{ photo.extended.license }}{% endif %}">
|
<img src="{{ photo.get_thumbnail_url }}" loading="lazy" class="img-thumbnail p-0" alt="{{ photo.title }}{% if photo.date_taken %} - {{ photo.date_taken|date }} {{ photo.date_taken|time }}{% endif %} - {{ photo.owner.get_full_name }}{% if photo.license %} - {{ photo.license }}{% endif %}">
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">{{ gallery.title }}</h5>
|
<h5 class="card-title">{{ gallery.title }}</h5>
|
||||||
{% if gallery.extended.date_start %}<p class="card-text text-muted small mb-0">{{ gallery.extended.date_start }}{% if gallery.extended.date_end and gallery.extended.date_end != gallery.extended.date_start %} - {{ gallery.extended.date_end }}{% endif %}</p>{% endif %}
|
{% if gallery.date_start %}<p class="card-text text-muted small mb-0">{{ gallery.date_start }}{% if gallery.date_end and gallery.date_end != gallery.date_start %} - {{ gallery.date_end }}{% endif %}</p>{% endif %}
|
||||||
<a href="{{ gallery.get_absolute_url }}" class="stretched-link"></a>
|
<a href="{{ gallery.get_absolute_url }}" class="stretched-link"></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
from django.urls import path, re_path
|
from django.urls import path, re_path
|
||||||
from photologue.views import GalleryArchiveIndexView, GalleryYearArchiveView, PhotoDetailView
|
|
||||||
|
|
||||||
from .views import CustomGalleryDetailView, GalleryDownload, GalleryUpload, TagDetail
|
from .views import (CustomGalleryDetailView, GalleryArchiveIndexView,
|
||||||
|
GalleryDownload, GalleryUpload, GalleryYearArchiveView,
|
||||||
|
PhotoDetailView, TagDetail)
|
||||||
|
|
||||||
# Rather than using photologue default router, we redefine our own router
|
|
||||||
# with login and permission checks.
|
|
||||||
app_name = 'photologue'
|
app_name = 'photologue'
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('tag/<slug:slug>/', TagDetail.as_view(), name='tag-detail'),
|
path('tag/<slug:slug>/', TagDetail.as_view(), name='tag-detail'),
|
||||||
|
|
@ -1,13 +1,31 @@
|
||||||
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.dates import ArchiveIndexView, YearArchiveView
|
||||||
from django.views.generic.detail import DetailView
|
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):
|
class GalleryDateView(LoginRequiredMixin):
|
||||||
queryset = Gallery.objects.filter(is_public=True)
|
queryset = Gallery.objects.filter(is_public=True)
|
||||||
date_field = 'extended__date_start'
|
date_field = 'date_start'
|
||||||
uses_datetime_field = False # Fix related object access
|
uses_datetime_field = False # Fix related object access
|
||||||
allow_empty = True
|
allow_empty = True
|
||||||
|
|
||||||
|
|
@ -22,3 +40,125 @@ class GalleryYearArchiveView(GalleryDateView, YearArchiveView):
|
||||||
|
|
||||||
class PhotoDetailView(LoginRequiredMixin, DetailView):
|
class PhotoDetailView(LoginRequiredMixin, DetailView):
|
||||||
queryset = Photo.objects.filter(is_public=True)
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
|
|
||||||
class PhotologueCustomConfig(AppConfig):
|
|
||||||
default_auto_field = 'django.db.models.AutoField'
|
|
||||||
name = 'photologue_custom'
|
|
||||||
|
|
@ -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',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -1,143 +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
|
|
||||||
from PIL import Image
|
|
||||||
from taggit.models import Tag
|
|
||||||
|
|
||||||
from .forms import UploadForm
|
|
||||||
from .models import PhotoExtended
|
|
||||||
|
|
||||||
|
|
||||||
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(extended__tags__slug=current_tag) \
|
|
||||||
.order_by('-extended__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 extended and owner to reduce database lag
|
|
||||||
context['photos'] = self.object.public().select_related('extended__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)
|
|
||||||
|
|
||||||
# Filter on owner
|
|
||||||
if 'owner' in self.kwargs:
|
|
||||||
context['photos'] = context['photos'].filter(extended__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.extended.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))
|
|
||||||
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
|
|
||||||
|
|
||||||
# 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)
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
django-allauth>=0.44
|
django-allauth>=0.44
|
||||||
django-crispy-forms~=1.7
|
django-crispy-forms~=1.7
|
||||||
django-taggit>=1.5.0
|
|
||||||
Django>=2.2.20
|
Django>=2.2.20
|
||||||
ExifRead>=2.1.2
|
ExifRead>=2.1.2
|
||||||
git+https://gitlab.crans.org/bde/allauth-note-kfet.git
|
git+https://gitlab.crans.org/bde/allauth-note-kfet.git
|
||||||
|
|
|
||||||
4
tox.ini
4
tox.ini
|
|
@ -12,7 +12,7 @@ deps =
|
||||||
-r{toxinidir}/requirements.txt
|
-r{toxinidir}/requirements.txt
|
||||||
coverage
|
coverage
|
||||||
commands =
|
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
|
coverage report -m
|
||||||
|
|
||||||
[testenv:linters]
|
[testenv:linters]
|
||||||
|
|
@ -26,7 +26,7 @@ deps =
|
||||||
pep8-naming
|
pep8-naming
|
||||||
pyflakes
|
pyflakes
|
||||||
commands =
|
commands =
|
||||||
flake8 photo21 photologue photologue_custom
|
flake8 photo21 photologue
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
ignore = W503, I100, I101
|
ignore = W503, I100, I101
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue