Search code examples
jsondjangorestdatatablestastypie

Datatables with JSON Ajax datasource


Given a RESTful API built with Django 1.10 and Django-Tastypie 0.13.3 that gives the following response to a GET request:

{
    "meta": {
        "limit": 20,
        "next": "/api/v1/serverwinpatchresults/?limit=20&offset=20",
        "offset": 0,
        "previous": null,
        "total_count": 178
    },
    "objects": [
      {
        "date_installed": true,
        "downloaded": "True",
        "installed": "True",
        "patch_guid": {
            "dateinserted": "2016-08-14T09:34:47",
            "description": "https://support.microsoft.com/en-us/kb/2757638",
            "guid": "013af7d6-ec9f-4def-ae41-007d211f9fbc",
            "kb": 0,
            "needsreboot": "False",
            "resource_uri": "/api/v1/winpatches/013af7d6-ec9f-4def-ae41-007d211f9fbc/",
            "severity": "Moderate",
            "title": "Security Update for Windows Server 2008 R2 x64 Edition (KB2757638)",
            "userinput": "False"
        },
        "patch_result_id": "16013af7d6-ec9f-4def-ae41-007d211f9fbc",
        "resource_uri": "/api/v1/serverwinpatchresults/16013af7d6-ec9f-4def-ae41-007d211f9fbc/",
        "server": {
            "active": 1,
            "cpuarch": null,
            "customer": {
                "active": 1,
                "customer_id": 1,
                "name": "SOMENAME",
                "resource_uri": "/api/v1/customers/1/"
            },
            "customer_0": null,
            "customername": null,
            "domain": null,
            "fqdn": null,
            "host": null,
            "hwaddr_interfaces": null,
            "ip4": null,
            "ip6": null,
            "kernel": null,
            "kernelrelease": null,
            "master": null,
            "mem_total": null,
            "nodename": "SOMENODENAME",
            "num_cpus": null,
            "num_gpus": null,
            "os": {
                "active": 1,
                "name": "Windows",
                "os_id": 1,
                "resource_uri": "/api/v1/operatingsystems/1/"
            },
            "os_0": null,
            "os_family": null,
            "osrelease": null,
            "path": null,
            "resource_uri": "/api/v1/servers/16/",
            "saltversion": null,
            "server_id": 16,
            "shell": null,
            "tag_name": "SOMETAGNAME",
            "timezone": null,
            "uuid": null,
            "windows_domain": null,
            "wintel": null,
            "zmqversion": null
        }
    },
    ...
  ]
}

The following HTML:

<table id="patch_report" class="table table-striped table-bordered" cellspacing="0" width="100%">
  <thead>
      <tr>
          <th>Server</th>
          <th>Guid</th>
          <th>Downloaded</th>
          <th>Installed</th>
          <th>Date</th>
      </tr>
  </thead>
  <tbody>
  </tbody>
</table>

And the following JavaScript:

<script>
$(document).ready(function() {
    $('#patch_report').DataTable( {
        "serverSide": true,
        "ajax": {
            "type" : "GET",
            "url": "http://localhost:8000/api/v1/serverwinpatchresults/",
            "dataSrc": "objects"
        },
        "columns": [
            { "data": "server.nodename" },
            { "data": "patch_guid.guid" },
            { "data": "downloaded" },
            { "data": "installed" },
            { "data": "date_installed" }
        ]
    } );
} );
</script>

I am trying to figure out why my table is failing to render. Not only is it failing to render, but it is failing to render without error.

When I look at the requests being made from the Django dev server in PyCharm I see the following:

"GET /api/v1/serverwinpatchresults/?draw=1&columns%5B0%5D%5Bdata%5D=server.nodename&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=patch_guid.guid&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=downloaded&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=installed&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=date&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&order%5B0%5D%5Bcolumn%5D=0&order%5B0%5D%5Bdir%5D=asc&start=0&length=10&search%5Bvalue%5D=&search%5Bregex%5D=false&_=1471378715102 HTTP/1.1" 200 30115

which, to me, seems like the GET request from Datatables to my API is working and returning something. However nothing is rendered except the search bar, number of entries selector, and the table headers. I thought I would be able to pull the data I wanted out of the API using columns to drill down the exact fields I need. However this does not appear to be the case.


So this was an operator error. It appears I was calling the API via localhost while loading the page as 127.0.0.1 so cross-origin was kicking in.

The issue now is that pagination does not work, as well as filtering. I believe Brian Kates is correct, and I am failing to consume the metadata from the API via Datatables for things like the number of total records and the number of filtered records, however I am unable to find solid examples in the documentation on how to implement this.


Solution

  • To make things simpler, I would start by turning server side off. It's not related to an ajax datasource and requires you to return extra parameters. For example, you need to return the number of total records and the number of filtered records. I didn't see that in your code. See the documentation: https://datatables.net/examples/server_side/. Because you've omitted those params, that could be why you are not seeing anything.

    Edit: Look at the server side processing docs: https://datatables.net/manual/server-side#Sent-parameters. Paging works by sending a start and a length in the sent paramters. You obviously need to use that information to query for your data.

    As for server side filtering, you need to set the records total and records filtered.