Skip to content

Instantly share code, notes, and snippets.

@whosaysni
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save whosaysni/6b6f367add94e7bde097 to your computer and use it in GitHub Desktop.
Save whosaysni/6b6f367add94e7bde097 to your computer and use it in GitHub Desktop.
Djangoで dataTables.js を使うためのクエリパーザ
# 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
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