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