views.py 6.67 KB
Newer Older
1
# coding: utf-8
2
3
4

from copy import copy

Jamesie Pic's avatar
Jamesie Pic committed
5
6
7
from django import http

import unicodecsv as csv
8

Jamesie Pic's avatar
Jamesie Pic committed
9

10
11
12
13
14
15
16
17
18
19
20
class ActiveLegislatureMixin(object):
    """
    Mixin for views that can switch between active legislature and all data
    """

    default_active_only = True

    def get(self, *args, **kwargs):
        self.set_active_only()
        return super(ActiveLegislatureMixin, self).get(*args, **kwargs)

21
22
23
24
25
26
27
28
    def override_active_only(self):
        """
        Redefine this method to override active legislature selection
        - return None to enable user choice
        - return True or False to disable user choice and set active state
        """
        return None

29
30
31
32
33
34
35
36
    def set_active_only(self):
        if 'active_only' in self.request.GET:
            self.request.session['active_only'] = \
                self.request.GET['active_only'] == '1'
        elif 'active_only' not in self.request.session:
            self.request.session['active_only'] = self.default_active_only

    def get_active_only(self):
37
38
        overriden = self.override_active_only()
        if overriden is None:
39
40
41
42
            if 'active_only' in self.request.session:
                return self.request.session['active_only']
            else:
                return self.default_active_only
43
44
        else:
            return overriden
45
46
47

    def get_context_data(self, **kwargs):
        c = super(ActiveLegislatureMixin, self).get_context_data(**kwargs)
48
49
        if self.override_active_only() is None:
            c['active_only'] = self.get_active_only()
50
51
52
        return c


53
54
55
class SortMixin(object):
    """
    Mixin for views that allow sorting.
Nicolas Joyard's avatar
Nicolas Joyard committed
56
57
58
59
60
61
62
63
64
65
66
    The sort_modes attribute should be defined to a dict as such:
    {
        'mode1': {
            'order': 42,
            'label': 'mode label',
            'fields': ['-field1', 'field2', ...]
        },
        ...
    }

    The sort_default attribute should contain the default sorting mode.
67
    """
Nicolas Joyard's avatar
Nicolas Joyard committed
68
69
    sort_modes = {}
    sort_default = None
70
    sort_session_prefix = ''
71
72
73
74
75

    def get(self, *args, **kwargs):
        self.set_sorting()
        return super(SortMixin, self).get(*args, **kwargs)

Nicolas Joyard's avatar
Nicolas Joyard committed
76
77
    def _session_get_sort(self):
        k = '%s_sort' % self.sort_session_prefix
78
79
        return self.request.session[k]

Nicolas Joyard's avatar
Nicolas Joyard committed
80
81
    def _session_set_sort(self, value):
        k = '%s_sort' % self.sort_session_prefix
82
83
        self.request.session[k] = value

Nicolas Joyard's avatar
Nicolas Joyard committed
84
85
    def _session_sort_exists(self):
        k = '%s_sort' % self.sort_session_prefix
86
87
        return k in self.request.session

88
    def set_sorting(self):
Nicolas Joyard's avatar
Nicolas Joyard committed
89
90
91
92
        if 'sort' in self.request.GET:
            self._session_set_sort(self.request.GET['sort'])
        elif not self._session_sort_exists():
            self._session_set_sort(self.sort_default)
93

Nicolas Joyard's avatar
Nicolas Joyard committed
94
95
        if self._session_get_sort() not in self.sort_modes:
            self._session_set_sort(self.sort_default)
96
97
98
99

    def get_context_data(self, **kwargs):
        c = super(SortMixin, self).get_context_data(**kwargs)

Nicolas Joyard's avatar
Nicolas Joyard committed
100
101
102
        c['sort_querystring'] = copy(self.request.GET)
        if 'sort' in c['sort_querystring']:
            del c['sort_querystring']['sort']
103
104

        c['sort'] = {
Nicolas Joyard's avatar
Nicolas Joyard committed
105
106
107
            'modes': [{'id': k, 'label': v['label'], 'order': v['order']}
                      for k, v in self.sort_modes.iteritems()],
            'mode': self._session_get_sort()
108
109
110
111
112
        }
        return c

    def get_queryset(self):
        qs = super(SortMixin, self).get_queryset()
Nicolas Joyard's avatar
Nicolas Joyard committed
113
114
115
        if self._session_get_sort() in self.sort_modes:
            mode = self.sort_modes[self._session_get_sort()]
            qs = qs.order_by(*mode['fields'])
116
117
118
        return qs


Jamesie Pic's avatar
Jamesie Pic committed
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
class PaginationMixin(object):
    pagination_limits = (12, 24, 48, 96)

    def get(self, *args, **kwargs):
        self.set_paginate_by()
        return super(PaginationMixin, self).get(*args, **kwargs)

    def set_paginate_by(self):
        if 'paginate_by' in self.request.GET:
            self.request.session['paginate_by'] = \
                self.request.GET['paginate_by']

        elif 'paginate_by' not in self.request.session:
            self.request.session['paginate_by'] = 12

    def get_paginate_by(self, queryset):
        return self.request.session['paginate_by']

    def get_page_range(self, page):
        pages = []

Jamesie Pic's avatar
Jamesie Pic committed
140
        if page and page.paginator.num_pages != 1:
Jamesie Pic's avatar
Jamesie Pic committed
141
142
143
144
145
146
147
148
149
150
151
            for i in page.paginator.page_range:
                if page.number - 4 < i < page.number + 4:
                    pages.append(i)

        return pages

    def get_context_data(self, **kwargs):
        c = super(PaginationMixin, self).get_context_data(**kwargs)
        c['pagination_limits'] = self.pagination_limits
        c['paginate_by'] = self.request.session['paginate_by']
        c['page_range'] = self.get_page_range(c['page_obj'])
Nicolas Joyard's avatar
Nicolas Joyard committed
152
153
154
        c['pagination_querystring'] = copy(self.request.GET)
        if 'page' in c['pagination_querystring']:
            del c['pagination_querystring']['page']
Jamesie Pic's avatar
Jamesie Pic committed
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
        return c


class GridListMixin(object):
    def set_session_display(self):
        if self.request.GET.get('display') in ('grid', 'list'):
            self.request.session['display'] = self.request.GET.get('display')

        if 'display' not in self.request.session:
            self.request.session['display'] = 'grid'

    def get(self, *args, **kwargs):
        self.set_session_display()
        return super(GridListMixin, self).get(*args, **kwargs)

    def get_template_names(self):
        return [t.replace('_list', '_%s' % self.request.session['display'])
                for t in super(GridListMixin, self).get_template_names()]

    def get_context_data(self, **kwargs):
        c = super(GridListMixin, self).get_context_data(**kwargs)
        c['grid_list'] = True
        return c
Jamesie Pic's avatar
Jamesie Pic committed
178
179
180


class CSVDownloadMixin(object):
Nicolas Joyard's avatar
Nicolas Joyard committed
181
182
183
184
185
186
    def get_context_data(self, **kwargs):
        c = super(CSVDownloadMixin, self).get_context_data(**kwargs)
        c['csv'] = True
        c['csv_querystring'] = copy(self.request.GET)
        return c

Jamesie Pic's avatar
Jamesie Pic committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
    def get_paginate_by(self, queryset):
        if self.request.GET.get('csv', None) is None:
            return super(CSVDownloadMixin, self).get_paginate_by(queryset)
        return None

    def render_to_csv_response(self, context, **kwargs):
        response = http.HttpResponse(content_type='text/csv')

        writer = csv.writer(response)
        for result in self.get_csv_results(context, **kwargs):
            writer.writerow(self.get_csv_row(result))

        response['Content-Disposition'] = 'attachment; filename="%s.csv"' % (
            self.csv_name)

        return response

    def render_to_response(self, context, **kwargs):
        if self.request.GET.get('csv', None) is None:
            return super(CSVDownloadMixin, self).render_to_response(
                context, **kwargs)

        return self.render_to_csv_response(context, **kwargs)