ajax_slickgrid.py
4.43 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
#-*- coding:utf-8 -*-
from accounts.models import filtering_mode
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',
}
def __init__(self, filter, sort_rules, mask, user):
self.filter = filter
self.sort_rules = sort_rules
self.mask = mask
self.user = user
def filtering_mode(self):
return filtering_mode(self.user)
def get_queryset(self):
return self.model.objects.all()
def get_empty_queryset(self):
return self.model.objects.none()
def apply_filter_rule(self, queryset, rule):
lookup = self.lookup_translation[rule['op']]
negated = (lookup[0] == '-')
lookup = lookup.lstrip('-')
field = self.filter_field_translation.get(rule['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 apply_mask(self, queryset):
pass # abstract
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 self.filtering_mode():
queryset = self.apply_mask(queryset)
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):
queryset = self.apply_filter()
count = queryset.count()
if count > 0 and self.mask == '':
return 0
if self.filtering_mode():
queryset = self.apply_mask(queryset)
if queryset.count() > 0:
whole_queryset = queryset
queryset = self.filter_from(
queryset, from_value=self.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()
if self.filtering_mode():
queryset = self.apply_mask(queryset)
return self.sort_queryset(queryset)
def count_pages(self, 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