ajax_slickgrid.py
6.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# -*- coding: utf-8 -*-
from django.db.models import Q
from dictionary.models import FreqLevel
class SlickGridQuery(object):
model = None
sort_field = None
literal_filter_fields = []
filter_field_translation = {}
select_related = []
default_columns = ()
column_data = {}
lookup_translation = {
'eq': 'exact',
'ne': '-exact',
'bw': 'startswith',
'bn': '-startswith',
'ew': 'endswith',
'en': '-endswith',
'cn': 'contains',
'nc': '-contains',
're': 'regex',
'nr': '-regex',
'eqcnt': 'exact',
'le': 'lte',
'ge': 'gte',
'in': 'in',
'-in': '-in',
'isnull': 'isnull',
'-isnull': '-isnull',
'belongs': 'in',
'-belongs': '-in',
}
def __init__(self, query_params, columns=None):
self.query_params = query_params
self.filter = query_params['filter']
self.sort_rules = query_params['sort_rules']
if columns:
self.columns = tuple(columns)
else:
self.columns = self.default_columns
# tymczasowa łata
self.columns = tuple(
column for column in self.columns if column is not None)
def get_queryset(self):
return self.model.objects.all()
def get_empty_queryset(self):
return self.model.objects.none()
def translate_filter_field(self, field):
if field in self.literal_filter_fields:
return field
elif field in self.filter_field_translation:
return self.filter_field_translation[field]
else:
raise ValueError(u'Incorrect filter field: %s.' % field)
def apply_filter_rule(self, queryset, rule):
# Specjalna obsługa frekwencji
print rule
if rule['field'] == 'freq_level':
negated = (rule['op'][0] == '-')
lvl = FreqLevel.objects.get(id = int(rule['data'])).level
if negated:
queryset = queryset.filter(Q(freq__lt = lvl) | Q(freq__isnull = True))
else:
queryset = queryset.filter(freq__gte = lvl)
else:
lookup = self.lookup_translation[rule['op']]
negated = (lookup[0] == '-')
lookup = lookup.lstrip('-')
field = self.translate_filter_field(rule['field'])
data = rule['data']
if not data and lookup == 'in':
lookup = 'isnull'
data = not negated
negated = False
elif rule['op'] in ['eqcnt', 'le', 'ge']: #wartości numeryczne
if not data: # przy pustej wartości wybierz "null"
lookup = 'isnull'
data = True
negated = False
else:
try:
data = int(data)
except: # przy niewłaściwej wartości zwróc pusty zestaw
lookup = 'in'
data = []
negated = False
arg = {(field + '__' + lookup): data}
try:
if negated:
queryset = queryset.exclude(**arg).distinct()
else:
queryset = queryset.filter(**arg).distinct()
except ValueError:
print "Byl except"
pass
return queryset
def apply_filter(self):
queryset = self.get_queryset()
if self.filter:
if self.filter['group_op'] == 'AND':
for rule in self.filter['rules']:
queryset = self.apply_filter_rule(queryset, rule)
elif self.filter['group_op'] == 'OR':
new_queryset = self.get_empty_queryset()
for rule in self.filter['rules']:
new_queryset |= self.apply_filter_rule(queryset, rule)
queryset = new_queryset
return queryset
def sort_queryset(self, queryset):
order_list = [self.sort_field]
return queryset.extra(order_by=order_list)
def filter_from(self, queryset, from_value, upward):
lookup = '__gte' if upward else '__lte'
return queryset.filter(**{self.sort_field + lookup: from_value})
# indeks wiersza w danym sortowaniu, w którym
# znajdzie się rekord o danym id
def row_index(self, record_id):
selected = self.model.objects.get(pk=record_id)
queryset = self.apply_filter()
if selected not in queryset:
return None
data = getattr(selected, self.sort_field)
preceding = self.filter_from(
queryset, from_value=data, upward=False)
return max(preceding.count() - 1, 0)
def search_index(self, mask):
queryset = self.apply_filter()
count = queryset.count()
if count > 0 and mask == '':
return 0
if queryset.count() > 0:
whole_queryset = queryset
queryset = self.filter_from(
queryset, from_value=mask, upward=True)
if queryset.count() == 0:
queryset = whole_queryset
queryset = self.sort_queryset(queryset)
index = self.row_index(queryset[0].id)
else:
index = 0
return index
def get_sorted_queryset(self):
queryset = self.apply_filter()
return self.sort_queryset(queryset)
@staticmethod
def count_pages(from_page, to_page, limit):
start = limit * from_page
pages = to_page - from_page + 1
response_rowcount = limit * pages
return start, response_rowcount
def response_row(self, record):
return dict((column, self.column_data[column](record))
for column in ('id', 'scheme', 'hidden') + self.columns)
def prepare_rows(self, records):
return [self.response_row(record) for record in records]
def get_page(self, from_page, to_page, limit):
queryset = self.get_sorted_queryset()
if self.select_related:
queryset = queryset.select_related(*self.select_related)
count = queryset.count()
start, response_rowcount = self.count_pages(from_page, to_page, limit)
records = queryset[start:start + response_rowcount]
return self.prepare_rows(records), count