Last active
August 29, 2015 14:01
-
-
Save whosaysni/6b6f367add94e7bde097 to your computer and use it in GitHub Desktop.
Djangoで dataTables.js を使うためのクエリパーザ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: utf-8 | |
"""dataTables.js 用のクエリパーザ | |
""" | |
import re | |
class DataTablesQueryParser(object): | |
"""dataTables.js 用のクエリパーザ | |
""" | |
def __init__(self, request, column_map=dict(), method='POST'): | |
"""しょきか | |
""" | |
self.column_map = column_map | |
params = dict(getattr(request, method)) | |
js_boolean = lambda s: dict(true=True, false=False).get(s, False) | |
self.draw = int(params.pop('draw', 0)[0]) | |
self.start = int(params.pop('start', 0)[0]) | |
self.length = int(params.pop('length', 0)[0]) | |
self.search_value = params.pop('search[value]', [''])[0] | |
self.search_regex = js_boolean(params.pop('search[regex]', '')[0]) | |
self.columns = {} | |
self.order = {} | |
for key, value in params.items(): | |
value = value[0] | |
for param, attr, datatype in ( | |
('columns', 'data', str), | |
('columns', 'name', str), | |
('columns', 'searchable', js_boolean), | |
('columns', 'orderable', js_boolean), | |
('order', 'column', int), | |
('order', 'dir', str)): | |
pattern = r'^(?P<param>%s)\[(?P<index>\d+)\]\[(?P<attr>%s)\]$' %(param, attr) | |
match = re.match(pattern, key) | |
if match: | |
captured = match.groupdict() | |
index = int(captured['index']) | |
attrs_for_index = getattr(self, param).setdefault(index, {}) | |
attrs_for_index[attr] = datatype(value) | |
def interpret_field(self, field): | |
"""サブクラスでオーバライドする。リストを返すので注意。 | |
""" | |
return self.column_map.get(field, [field]) | |
def get_order_by_fields(self): | |
""".order_by に使うフィールドのリストを返す | |
""" | |
fields = [] | |
for column_index in sorted(self.order.keys()): | |
prefix = '' | |
if self.order[column_index].get('dir', 'asc')=='desc': | |
prefix='-' | |
fields.extend( | |
prefix+field | |
for field in self.interpret_field( | |
self.columns[self.order[column_index]['column']]['data'])) | |
return fields | |
def get_search_fields(self): | |
"""検索用の Q に使うフィールドのリストを返す | |
""" | |
fields = [] | |
for column_index in sorted(self.columns.keys()): | |
if self.columns[column_index].get('searchable', True): | |
fields.extend( | |
self.interpret_field(self.columns[column_index]['data'])) | |
return fields |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from my_app.models import MyModel | |
from django.db.models import Q | |
def my_view(request): | |
queryset = MyModel.objects.all() | |
qs_tuned = queryset.all() | |
dt_parser = DataTablesQueryParser(request) | |
if dt_parser.search_value: | |
q_obj = Q() | |
for field in dt_parser.get_search_fields(): | |
q_obj |= Q(**{field+'__contains': dt_parser.search_value }) | |
qs_tuned = qs_tuned.filter(Q) | |
order_fields = dt_parser.get_order_by_fields() | |
if order_fields: | |
qs_tuned = qs_tuned.order_by(*order_fields) | |
qs_tuned_slice = qs_tuned[dt_parser.start:dt_parser.start+dt_parser.length] | |
json_src = dict( | |
draw=dt_parser.draw, | |
recordsTotal=queryset.count(), | |
recordsFiltered=qs_tuned.count(), | |
data=[dict(foo=obj.foo, bar=obj.get_bar_display()) for obj in qs_tuned_slice]) | |
return HttpResponse(json.dumps(json_src), content_type='text/json') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment