ajax_slickgrid.py
4.99 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
# -*- coding: utf-8 -*-
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',
'le': 'lte',
'ge': 'gte',
'in': 'in',
'-in': '-in',
'isnull': 'isnull',
'-isnull': '-isnull',
}
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):
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).distinct()
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