izimobil / django-rest-framework-datatables

Seamless integration between Django REST framework and Datatables.
http://django-rest-framework-datatables.readthedocs.io/en/latest/
MIT License
394 stars 88 forks source link

FieldError when sorting a column which defines a function as the 'data' attribute #86

Open matthewhegarty opened 4 years ago

matthewhegarty commented 4 years ago

My Javascript defines a function for the columns.data attribute:

  $('#player-table').DataTable({
      "serverSide": true,
      "ajax": {
          "url": "{% url "api:player-list" %}?format=datatables",
      },
      "columns": [
        "data": function ( row, type, val, meta ) {
            return row.my_val;
        }
     ]   
})

This works fine when displaying the table - the values are rendered correctly. However, when sorting the column, this sends a request which triggers a crash with FieldError:

Exception Type: FieldError at /api/player/
Exception Value: Cannot resolve keyword 'function' into field. 

Sure enough, the request sends data=function, and I thought that this was the source of the issue, but this actually gets sent with successful requests as well.

Crashes:

http://localhost:8000/api/player/?format=datatables&draw=6&columns%5B0%5D%5Bdata%5D=uid&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=function&columns%5B1%5D%5Bname%5D=&columns%5B1%5D%5Bsearchable%5D=false&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=netreturn_total_90_day&columns%5B2%5D%5Bname%5D=&columns%5B2%5D%5Bsearchable%5D=false&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=deposit_total_90_day&columns%5B3%5D%5Bname%5D=&columns%5B3%5D%5Bsearchable%5D=false&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=withdrawal_total_90_day&columns%5B4%5D%5Bname%5D=&columns%5B4%5D%5Bsearchable%5D=false&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=id&columns%5B5%5D%5Bname%5D=&columns%5B5%5D%5Bsearchable%5D=false&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=1&order%5B0%5D%5Bdir%5D=desc&start=0&length=10&search%5Bvalue%5D=&search%5Bregex%5D=false&range=28&_=1591817768441

Returns OK:

http://localhost:8000/api/player/?format=datatables&draw=1&columns%5B0%5D%5Bdata%5D=uid&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=function&columns%5B1%5D%5Bname%5D=&columns%5B1%5D%5Bsearchable%5D=false&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=netreturn_total_90_day&columns%5B2%5D%5Bname%5D=&columns%5B2%5D%5Bsearchable%5D=false&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=deposit_total_90_day&columns%5B3%5D%5Bname%5D=&columns%5B3%5D%5Bsearchable%5D=false&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=withdrawal_total_90_day&columns%5B4%5D%5Bname%5D=&columns%5B4%5D%5Bsearchable%5D=false&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=id&columns%5B5%5D%5Bname%5D=&columns%5B5%5D%5Bsearchable%5D=false&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&range=28&_=1591817934274

Stack trace:

drfdt_st1.txt

Workaround

Very very nasty hack is to declare an attribute on the model in question called function. This prevents the crash, but sorting still does not work.

matthewhegarty commented 4 years ago

I've reproduced the issue here.

To reproduce:

sandeepbalagopal09 commented 4 years ago

I am getting the error when search is done. custom functions are not working.

sandeepbalagopal09 commented 4 years ago

hey @matthewhegarty take a look at #83 . set orderable: false, searchable: false,

https://datatables.net/reference/option/columns.orderable

izimobil commented 3 years ago

This should be documented, as well as other cases where setting orderable: false, searchable: false is necessary to prevent a server side error. PR anyone ? @matthewhegarty @sandeepbalagopal09

lampslave commented 1 year ago

@izimobil why don't you want to use name as alternative to data in this case?

  $('#player-table').DataTable({
      "serverSide": true,
      "ajax": {
          "url": "{% url "api:player-list" %}?format=datatables",
      },
      "columns": [
        "data": function ( row, type, val, meta ) {
            return row.my_val;
        },
        "name": "my_val"
     ]   
})

Just modify that lines https://github.com/izimobil/django-rest-framework-datatables/blob/fab94a9e3d26bd6e393e341cb84d99a406b27db1/rest_framework_datatables/filters.py#L54-L65 like this

col = 'columns[%d][%s]'
data = get_param(request, col % (i, 'data'))
name = get_param(request, col % (i, 'name'))
if (data == 'function') and name:
    data = name

(not a full replacement, just for illustration).