Django 1.11; removed unused comments app.
[redakcja.git] / src / catalogue / templatetags / book_list.py
1 from __future__ import absolute_import
2
3 from re import split
4 from django.db.models import Q, Count
5 from django import template
6 from django.utils.translation import ugettext_lazy as _
7 from django.contrib.auth.models import User
8 from catalogue.models import Chunk, Image, Project
9
10 register = template.Library()
11
12
13 class ChunksList(object):
14     def __init__(self, chunk_qs):
15         self.chunk_qs = chunk_qs.select_related('book')
16         self.book_qs = chunk_qs.values('book_id')
17
18     def __getitem__(self, key):
19         if isinstance(key, slice):
20             return self.get_slice(key)
21         elif isinstance(key, int):
22             return self.get_slice(slice(key, key+1))[0]
23         else:
24             raise TypeError('Unsupported list index. Must be a slice or an int.')
25
26     def __len__(self):
27         return self.book_qs.count()
28
29     def get_slice(self, slice_):
30         book_ids = [x['book_id'] for x in self.book_qs[slice_]]
31         chunk_qs = self.chunk_qs.filter(book__in=book_ids)
32
33         chunks_list = []
34         book = None
35         for chunk in chunk_qs:
36             if chunk.book != book:
37                 book = chunk.book
38                 chunks_list.append(ChoiceChunks(book, [chunk]))
39             else:
40                 chunks_list[-1].chunks.append(chunk)
41         return chunks_list
42
43
44 class ChoiceChunks(object):
45     """
46         Associates the given chunks iterable for a book.
47     """
48
49     chunks = None
50
51     def __init__(self, book, chunks):
52         self.book = book
53         self.chunks = chunks
54
55
56 def foreign_filter(qs, value, filter_field, model, model_field='slug', unset='-'):
57     if value == unset:
58         return qs.filter(**{filter_field: None})
59     if not value:
60         return qs
61     try:
62         obj = model._default_manager.get(**{model_field: value})
63     except model.DoesNotExist:
64         return qs.none()
65     else:
66         return qs.filter(**{filter_field: obj})
67
68
69 def search_filter(qs, value, filter_fields):
70     if not value:
71         return qs
72     q = Q(**{"%s__icontains" % filter_fields[0]: value})
73     for field in filter_fields[1:]:
74         q |= Q(**{"%s__icontains" % field: value})
75     return qs.filter(q)
76
77
78 _states = [
79         ('publishable', _('publishable'), Q(book___new_publishable=True)),
80         ('changed', _('changed'), Q(_changed=True)),
81         ('published', _('published'), Q(book___published=True)),
82         ('unpublished', _('unpublished'), Q(book___published=False)),
83         ('empty', _('empty'), Q(head=None)),
84     ]
85 _states_options = [s[:2] for s in _states]
86 _states_dict = dict([(s[0], s[2]) for s in _states])
87
88
89 def document_list_filter(request, **kwargs):
90
91     def arg_or_GET(field):
92         return kwargs.get(field, request.GET.get(field))
93
94     if arg_or_GET('all'):
95         chunks = Chunk.objects.all()
96     else:
97         chunks = Chunk.visible_objects.all()
98
99     chunks = chunks.order_by('book__title', 'book', 'number')
100
101     if not request.user.is_authenticated():
102         chunks = chunks.filter(book__public=True)
103
104     state = arg_or_GET('status')
105     if state in _states_dict:
106         chunks = chunks.filter(_states_dict[state])
107
108     chunks = foreign_filter(chunks, arg_or_GET('user'), 'user', User, 'username')
109     chunks = foreign_filter(chunks, arg_or_GET('stage'), 'stage', Chunk.tag_model, 'slug')
110     chunks = search_filter(chunks, arg_or_GET('title'), ['book__title', 'title'])
111     chunks = foreign_filter(chunks, arg_or_GET('project'), 'book__project', Project, 'pk')
112     return chunks
113
114
115 @register.inclusion_tag('catalogue/book_list/book_list.html', takes_context=True)
116 def book_list(context, user=None):
117     request = context['request']
118
119     if user:
120         filters = {"user": user}
121         new_context = {"viewed_user": user}
122     else:
123         filters = {}
124         new_context = {
125             "users": User.objects.annotate(
126                 count=Count('chunk')).filter(count__gt=0).order_by(
127                 '-count', 'last_name', 'first_name'),
128             "other_users": User.objects.annotate(
129                 count=Count('chunk')).filter(count=0).order_by(
130                 'last_name', 'first_name'),
131                 }
132
133     new_context.update({
134         "filters": True,
135         "request": request,
136         "books": ChunksList(document_list_filter(request, **filters)),
137         "stages": Chunk.tag_model.objects.all(),
138         "states": _states_options,
139         "projects": Project.objects.all(),
140     })
141
142     return new_context
143
144
145
146 _image_states = [
147         ('publishable', _('publishable'), Q(_new_publishable=True)),
148         ('changed', _('changed'), Q(_changed=True)),
149         ('published', _('published'), Q(_published=True)),
150         ('unpublished', _('unpublished'), Q(_published=False)),
151         ('empty', _('empty'), Q(head=None)),
152     ]
153 _image_states_options = [s[:2] for s in _image_states]
154 _image_states_dict = dict([(s[0], s[2]) for s in _image_states])
155
156 def image_list_filter(request, **kwargs):
157
158     def arg_or_GET(field):
159         return kwargs.get(field, request.GET.get(field))
160
161     images = Image.objects.all()
162
163     if not request.user.is_authenticated():
164         images = images.filter(public=True)
165
166     state = arg_or_GET('status')
167     if state in _image_states_dict:
168         images = images.filter(_image_states_dict[state])
169
170     images = foreign_filter(images, arg_or_GET('user'), 'user', User, 'username')
171     images = foreign_filter(images, arg_or_GET('stage'), 'stage', Image.tag_model, 'slug')
172     images = search_filter(images, arg_or_GET('title'), ['title', 'title'])
173     images = foreign_filter(images, arg_or_GET('project'), 'project', Project, 'pk')
174     return images
175
176
177 @register.inclusion_tag('catalogue/image_table.html', takes_context=True)
178 def image_list(context, user=None):
179     request = context['request']
180
181     if user:
182         filters = {"user": user}
183         new_context = {"viewed_user": user}
184     else:
185         filters = {}
186         new_context = {
187             "users": User.objects.annotate(
188                 count=Count('image')).filter(count__gt=0).order_by(
189                 '-count', 'last_name', 'first_name'),
190             "other_users": User.objects.annotate(
191                 count=Count('image')).filter(count=0).order_by(
192                 'last_name', 'first_name'),
193                 }
194
195     new_context.update({
196         "filters": True,
197         "request": request,
198         "objects": image_list_filter(request, **filters),
199         "stages": Image.tag_model.objects.all(),
200         "states": _image_states_options,
201         "projects": Project.objects.all(),
202     })
203
204     return new_context