Reputation: 2960
Using DataTables jQuery plugin with serverSide = true (example here is small, but ultimately we want to handle large number of records). On initial request (first page load) everything works OK. DataTable looks great and it contains the expected data.
Request info
Request method = GET
Request args = ImmutableMultiDict([('draw', u'1'), ('columns[0][data]', u'client_user_id'), ('columns[1][name]', u''), ('columns[5][searchable]', u'true'), ('columns[5][name]', u''), ('columns[4][search][regex]', u'false'), ('columns[1][orderable]', u'true'), ('columns[4][orderable]', u'true'), ('columns[5][orderable]', u'true'), ('columns[2][orderable]', u'true'), ('columns[4][name]', u''), ('order[0][dir]', u'asc'), ('columns[1][search][regex]', u'false'), ('columns[3][name]', u''), ('columns[0][search][value]', u''), ('columns[2][searchable]', u'true'), ('columns[3][search][regex]', u'false'), ('extra_search', u'test'), ('columns[0][search][regex]', u'false'), ('columns[5][data]', u'last_login'), ('start', u'0'), ('columns[4][searchable]', u'true'), ('columns[0][searchable]', u'true'), ('columns[5][search][value]', u''), ('columns[3][searchable]', u'true'), ('columns[2][search][value]', u''), ('columns[2][search][regex]', u'false'), ('columns[1][data]', u'status'), ('columns[1][searchable]', u'true'), ('columns[5][search][regex]', u'false'), ('columns[0][orderable]', u'true'), ('columns[4][data]', u'client_id'), ('columns[0][name]', u''), ('columns[2][data]', u'lastname'), ('columns[3][data]', u'email_address'), ('search[value]', u''), ('columns[3][orderable]', u'true'), ('_', u'1484145221101'), ('columns[4][search][value]', u''), ('search[regex]', u'false'), ('columns[1][search][value]', u''), ('order[0][column]', u'0'), ('columns[2][name]', u''), ('length', u'10'), ('columns[3][search][value]', u'')])
127.0.0.1 - - [11/Jan/2017 09:33:41] "GET /client/rou/ajax/mwe?draw=1&columns%5B0%5D%5Bdata%5D=client_user_id&columns%5B0%5D%5Bname%5D=&columns%5B0%5D%5Bsearchable%5D=true&columns%5B0%5D%5Borderable%5D=true&columns%5B0%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B0%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B1%5D%5Bdata%5D=status&columns%5B1%5D%5Bname%5D=&columns%5B1%5D%5Bsearchable%5D=true&columns%5B1%5D%5Borderable%5D=true&columns%5B1%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B1%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B2%5D%5Bdata%5D=lastname&columns%5B2%5D%5Bname%5D=&columns%5B2%5D%5Bsearchable%5D=true&columns%5B2%5D%5Borderable%5D=true&columns%5B2%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B2%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B3%5D%5Bdata%5D=email_address&columns%5B3%5D%5Bname%5D=&columns%5B3%5D%5Bsearchable%5D=true&columns%5B3%5D%5Borderable%5D=true&columns%5B3%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B3%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B4%5D%5Bdata%5D=client_id&columns%5B4%5D%5Bname%5D=&columns%5B4%5D%5Bsearchable%5D=true&columns%5B4%5D%5Borderable%5D=true&columns%5B4%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B4%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B5%5D%5Bdata%5D=last_login&columns%5B5%5D%5Bname%5D=&columns%5B5%5D%5Bsearchable%5D=true&columns%5B5%5D%5Borderable%5D=true&columns%5B5%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B5%5D%5Bsearch%5D%5Bregex%5D=false&order%5B0%5D%5Bcolumn%5D=0&order%5B0%5D%5Bdir%5D=asc&start=0&length=10&search%5Bvalue%5D=&search%5Bregex%5D=false&extra_search=test&_=1484145221101 HTTP/1.1" 200 -
...and data is returned from the server. However any interaction with the DataTable (e.g., clicking column heading to sort result, or typing in the search box) and subsequent ajax requests look like this:
Request info when attempting search or sort
Request method = GET
Request args = ImmutableMultiDict([('[object Object]', u''), ('_', u'1484145221102')])
127.0.0.1 - - [11/Jan/2017 09:33:46] "GET /client/rou/ajax/mwe?[object%20Object]&_=1484145221102 HTTP/1.1" 200 -
Why in the first case do we get all the parameters OK, and in the second case we get [Object object]? What changes are needed so that DataTables makes valid requests?
Python (using Flask)
@blueprint.route('/rou/ajax/mwe', methods=("GET", "POST"))
def b_ajax_mwe():
error = False
error_text = None
data = []
print("Request method = {}".format(request.method))
print("Request args = {}".format(request.args))
draw = request.args.get('draw') or 1
try:
# Yes, I know this always returns same result... for now
# once we have request from DataTable that's not "[Object object]"
# we will modify to return data based on request
query = ClientUser.query \
.filter(ClientUser.client_id == 2) \
.limit(10) \
.all()
data = [{'client_user_id': cu.client_user_id,
'status': cu.status,
'email_address': cu.email_address,
'lastname': cu.lastname,
'client_id': cu.client_id,
'last_login': cu.last_login} for cu in query]
except Exception, err:
error = True
error_text = str(err)
rows = ClientUser.query.count()
result = {'draw': draw,
'recordsTotal': rows,
'recordsFiltered': len(data),
'data': data}
if error:
result['error'] = error_text
return jsonify(result)
HTML (in head)
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs/dt-1.10.13/datatables.min.css"/>
HTML (in body)
<table class="table display" id="mwe_table">
<thead>
<tr>
<th>User ID</th>
<th>Status</th>
<th>Last name</th>
<th>Email</th>
<th>Client ID</th>
<th>Last login</th>
</tr>
</thead>
<tbody></tbody>
</table>
...
<script type="text/javascript" src="https://cdn.datatables.net/v/bs/dt-1.10.13/datatables.min.js"></script>
(jQuery 1.11 loaded before stuff from DataTables CDN, above)
JavaScript
$(document).ready(function () {
$('#mwe_table').DataTable({
processing: true,
serverSide: true,
ajax: {
method: 'GET',
url: '/client/rou/ajax/mwe',
},
"columns": [
{ "data": "client_user_id" },
{ "data": "status" },
{ "data": "lastname" },
{ "data": "email_address" },
{ "data": "client_id" },
{ "data": "last_login" }
]
});
});
No errors are reported in JavaScript console.
Upvotes: 3
Views: 1002
Reputation: 18145
I was unable to reproduce using the specified parameters, but think that I may have a workaround anyhow. You can explicitly tell DataTables how to serialize the request data.
For example:
$(document).ready(function () {
$('#mwe_table').DataTable({
processing: true,
serverSide: true,
ajax: {
url: '/client/rou/ajax/mwe',
data: function (d) {
console.log(d); // display all properties to console
return jQuery.param({
start: d.start,
length: d.length,
orderColumn: d.order[0].column,
orderDir: d.order[0].dir,
draw: d.draw
});
}
},
"columns": [
{ "data": "client_user_id" },
{ "data": "status" },
{ "data": "lastname" },
{ "data": "email_address" },
{ "data": "client_id" },
{ "data": "last_login" }
]
});
});
Notice that I am selectively sending some parameters by serializing a JavaScript object into application/x-www-form-urlencoded
using jQuery.param()
. For simplicity, the JavaScript object only has simple properties and no nested objects or arrays. The call to jQuery.param()
is probably unnecessary, but I left it in to be explicit.
Upvotes: 1