- {% for img in gallery.get_images %}
+ {% for img in images %}
-
- {% if gallery_mode.can_write %}
-
- {% endif %}
-
-
{% else %}
{% trans "Aucune image" %}.
@@ -111,6 +103,8 @@
{% endif %}
{% endif %}
+
+ {% include "misc/paginator.html" with position="bottom" %}
{% endblock %}
diff --git a/update.md b/update.md
index 519f8f0234..96ce8c610a 100644
--- a/update.md
+++ b/update.md
@@ -794,6 +794,11 @@ Utilisateur `zds`:
+ "-V mainfont=Merriweather -V monofont=\"SourceCodePro-Regular\" "
```
+Actions à faire pour activer le thème d'Halloween
+=================================================
+
+Ajouter `ZDS_APP['visual_changes'] = ['clem-halloween']` à `settings_prod.py`.
+
---
**Notes auxquelles penser lors de l'édition de ce fichier (à laisser en bas) :**
diff --git a/zds/forum/migrations/0001_initial.py b/zds/forum/migrations/0001_initial.py
index 23dff2927c..8006ac10f7 100644
--- a/zds/forum/migrations/0001_initial.py
+++ b/zds/forum/migrations/0001_initial.py
@@ -35,7 +35,6 @@ class Migration(migrations.Migration):
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('title', models.CharField(max_length=80, verbose_name=b'Titre')),
('subtitle', models.CharField(max_length=200, verbose_name=b'Sous-titre')),
- ('image', models.ImageField(upload_to=zds.forum.models.image_path_forum)),
('position_in_category', models.IntegerField(db_index=True, null=True, verbose_name=b'Position dans la cat\xc3\xa9gorie', blank=True)),
('slug', models.SlugField(unique=True, max_length=80)),
('category', models.ForeignKey(verbose_name=b'Cat\xc3\xa9gorie', to='forum.Category')),
diff --git a/zds/forum/models.py b/zds/forum/models.py
index 212ea0b5b8..ee59d86d3a 100644
--- a/zds/forum/models.py
+++ b/zds/forum/models.py
@@ -1,8 +1,5 @@
# coding: utf-8
-import os
-import string
-import uuid
import logging
from datetime import datetime, timedelta
from math import ceil
@@ -26,19 +23,6 @@ def sub_tag(tag):
return u"{0}".format(start + end)
-def image_path_forum(instance, filename):
- """
- Return path to an image.
- TODO: what is the usage of this function?
- :param instance:
- :param filename:
- :return:
- """
- ext = filename.split('.')[-1]
- filename = u'{}.{}'.format(str(uuid.uuid4()), string.lower(ext))
- return os.path.join('forum/normal', str(instance.pk), filename)
-
-
class Category(models.Model):
"""
A Category is a simple container for Forums.
@@ -101,8 +85,6 @@ class Meta:
Group,
verbose_name='Groupe autorisés (Aucun = public)',
blank=True)
- # TODO: A forum defines an image, but it doesn't seems to be used...
- image = models.ImageField(upload_to=image_path_forum)
category = models.ForeignKey(Category, db_index=True, verbose_name='Catégorie')
position_in_category = models.IntegerField('Position dans la catégorie',
@@ -303,7 +285,7 @@ def resolve_last_read_post_absolute_url(self):
"""
user = get_current_user()
if user is None or not user.is_authenticated():
- return self.resolve_first_post_url()
+ return self.first_unread_post().get_absolute_url()
else:
try:
pk, pos = self.resolve_last_post_pk_and_pos_read_by_user(user)
@@ -313,7 +295,7 @@ def resolve_last_read_post_absolute_url(self):
return '{}?page={}#p{}'.format(
self.get_absolute_url(), page_nb, pk)
except TopicRead.DoesNotExist:
- return self.resolve_first_post_url()
+ return self.first_unread_post().get_absolute_url()
def resolve_last_post_pk_and_pos_read_by_user(self, user):
"""get the primary key and position of the last post the user read
@@ -335,20 +317,6 @@ def resolve_last_post_pk_and_pos_read_by_user(self, user):
.order_by('position')\
.values('pk', "position").first().values()
- def resolve_first_post_url(self):
- """resolve the url that leads to this topic first post
-
- :return: the url
- """
- pk = Post.objects\
- .filter(topic__pk=self.pk)\
- .order_by('position')\
- .values('pk').first()
-
- return '{0}?page=1#p{1}'.format(
- self.get_absolute_url(),
- pk['pk'])
-
def first_unread_post(self, user=None):
"""
Returns the first post of this topics the current user has never read, or the first post if it has never read \
@@ -357,7 +325,6 @@ def first_unread_post(self, user=None):
:return: The first unread post for this topic and this user.
"""
- # TODO: Why 2 nearly-identical functions? What is the functional need of these 2 things?
try:
if user is None:
user = get_current_user()
diff --git a/zds/gallery/views.py b/zds/gallery/views.py
index ba2bf623ad..f5e41b2e90 100644
--- a/zds/gallery/views.py
+++ b/zds/gallery/views.py
@@ -30,7 +30,7 @@
import os
from django.utils.translation import ugettext_lazy as _
-from django.views.generic import DetailView, CreateView, UpdateView, DeleteView, FormView
+from django.views.generic import CreateView, UpdateView, DeleteView, FormView
from django.utils.decorators import method_decorator
from zds.tutorialv2.models.models_database import PublishableContent
@@ -125,25 +125,29 @@ def ensure_user_access(gallery, user, can_write=False):
return user_gallery
-class GalleryDetails(DetailView):
+class GalleryDetails(ZdSPagingListView):
"""Gallery details"""
-
- model = Gallery
+ object = UserGallery
template_name = "gallery/gallery/details.html"
- context_object_name = "gallery"
+ context_object_name = "images"
+ paginate_by = settings.ZDS_APP['gallery']['images_per_page']
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(GalleryDetails, self).dispatch(*args, **kwargs)
+ def get_queryset(self):
+ self.pkey = self.kwargs.pop('pk', None)
+ self.slug = self.kwargs.pop('slug', None)
+ self.gallery = get_object_or_404(Gallery, pk=self.pkey, slug=self.slug)
+ self.user_access = ensure_user_access(self.gallery, self.request.user, can_write=True)
+ return self.gallery.get_images().order_by('title')
+
def get_context_data(self, **kwargs):
context = super(GalleryDetails, self).get_context_data(**kwargs)
-
- context['gallery_mode'] = ensure_user_access(self.object, self.request.user)
- context['images'] = self.object.get_images()
+ context['gallery_mode'] = self.user_access
context['form'] = UserGalleryForm
- context['content_linked'] = PublishableContent.objects.filter(gallery__pk=self.object.pk).first()
-
+ context['gallery'] = self.gallery
return context
diff --git a/zds/settings.py b/zds/settings.py
index 8b78a22efb..5cdfce462d 100644
--- a/zds/settings.py
+++ b/zds/settings.py
@@ -469,6 +469,7 @@
'gallery': {
'image_max_size': 1024 * 1024,
'gallery_per_page': 21,
+ 'images_per_page': 21,
},
'article': {
'home_number': 3,
diff --git a/zds/utils/templatetags/tests/tests_date.py b/zds/utils/templatetags/tests/tests_date.py
index 065dea9d57..cef9c77091 100644
--- a/zds/utils/templatetags/tests/tests_date.py
+++ b/zds/utils/templatetags/tests/tests_date.py
@@ -4,7 +4,6 @@
from django.test import TestCase
from django.template import Context, Template
-from django.utils import timezone
class DateFormatterTest(TestCase):
@@ -109,10 +108,4 @@ def test_humane_time(self):
"{{ date_epoch | humane_time }}"
).render(self.context)
- # Since ZdS is in Europe/Paris, hours can be 0 or 1
- paris = timezone.pytz.timezone('Europe/Paris')
- is_dst = paris.localize(datetime.now()).dst() == timedelta(0, 3600)
-
- hour = 1 if is_dst else 0
-
- self.assertEqual(tr, u"jeudi 01 janvier 1970 à 0{}h00".format(hour))
+ self.assertEqual(tr, u"jeudi 01 janvier 1970 à 01h00")