ajax_slickgrid.py
4.56 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
# -*- coding: utf-8 -*-
class SlickGridQuery(object):
model = None
sort_field = None
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',
'le': 'lte',
'ge': 'gte',
'in': 'in',
'-in': '-in',
'isnull': 'isnull',
'-isnull': '-isnull',
}
def __init__(self, filter, sort_rules, columns=None):
self.filter = filter
self.sort_rules = sort_rules
if columns:
self.columns = tuple(columns)
else:
self.columns = self.default_columns
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):
return self.filter_field_translation.get(field, field)
def apply_filter_rule(self, queryset, rule):
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
arg = {(field + '__' + lookup): data}
if negated:
queryset = queryset.exclude(**arg)
else:
queryset = queryset.filter(**arg).distinct()
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') + 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