ajax_slickgrid.py
4.18 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
#-*- coding:utf-8 -*-
class SlickGridQuery(object):
model = None
sort_field = None
filter_field_translation = {}
select_related = []
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, user):
self.filter = filter
self.sort_rules = sort_rules
self.user = user
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']
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 queryset.count() == 0:
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):
pass # abstract
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