Django request.GET and jQuery Datatables

120 views
Skip to first unread message

Andrea

unread,
Jul 25, 2014, 7:08:33 AM7/25/14
to django...@googlegroups.com
Dear all,

I'm trying to let Django being able to answer to requests by jQuery-Datatables (http://datatables.net/).
Considering the example at this link (http://www.datatables.net/examples/data_sources/server_side.html) to fill up the jQuery-Datatables table with data provided by the server, a typical request has the following form:

    http://www.datatables.net/examples/server_side/scripts/server_processing.php?draw=2&columns%5B0%5D%5Bdata%5D=0&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=1&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=2&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=3&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=4&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=5&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=10&length=10&search%5Bvalue%5D=&search%5Bregex%5D=false&_=1406235319463

The problem, as I understand it, is basically that instead of pairs like "a=b", I get "a[0][x]=b".
Which is the best/commonly used way to deal with this kind of data?

With the legacy Datatables (http://legacy.datatables.net/usage/server-side), I could easily deal with the request, by creating a form like the following and filling it with the request.GET data, to easily handle the validation and casting.

    class DataTablesForm(forms.Form):
        iDisplayStart = forms.IntegerField(min_value=0)
        iDisplayLength = forms.IntegerField(min_value=-1)
        iSortingCols = forms.IntegerField(min_value=0, max_value=3)
        mDataProp_0 = forms.CharField()
        mDataProp_1 = forms.CharField()
        mDataProp_2 = forms.CharField()
        iSortCol_0 = forms.IntegerField(required=False, min_value=0, max_value=5)
        iSortCol_1 = forms.IntegerField(required=False, min_value=0, max_value=5)
        iSortCol_2 = forms.IntegerField(required=False, min_value=0, max_value=5)
        sSortDir_0 = forms.ChoiceField(required=False, choices=(('asc', 'asc'), ('desc', 'desc')))
        sSortDir_1 = forms.ChoiceField(required=False, choices=(('asc', 'asc'), ('desc', 'desc')))
        sSortDir_2 = forms.ChoiceField(required=False, choices=(('asc', 'asc'), ('desc', 'desc')))
        sEcho = forms.CharField(required=False)

and

    input_form = DataTablesForm(request.GET)

How do I deal though with the new format, i.e. "columns[i].name" instead of "mDataProp_(int)"?

I think the problem is how to deal with JSON formatted GET data within Django, if "JSON formatted GET data" makes any sense.

Thanks for your help,

Andrea

P.S. I've posted the same question on Stack Overflow: http://stackoverflow.com/questions/24943942/django-request-get-and-jquery-datatables

Tom Evans

unread,
Jul 25, 2014, 8:55:56 AM7/25/14
to django...@googlegroups.com
Write a constructor for the Form class that takes the data dict and
pre-processes it to have the variables that your Form requires.

Cheers

Tom

Andrea

unread,
Jul 25, 2014, 9:48:25 AM7/25/14
to django...@googlegroups.com
Hi Tom,

thanks for your answer.
I'm not sure I got it right, do you mean something like the following?

class DataTablesForm(forms.Form):
    def __init__(self, *args, **kwargs):
        super(DataTablesForm, self).__init__(*args, **kwargs)

        self.fields['_'] = forms.CharField()
           
        for i in range(0, 6):
            self.fields['columns[%d][data]' % i] = forms.CharField(required=False)
            self.fields['columns[%d][name]' % i] = forms.CharField(required=False)
            self.fields['columns[%d][orderable]' % i] = forms.BooleanField(required=False)
            self.fields['columns[%d][search][regex]' % i] = forms.BooleanField(required=False)
            self.fields['columns[%d][search][value]' % i] = forms.CharField(required=False)
            self.fields['columns[%d][searchable]' % i] = forms.BooleanField(required=False)
           
            self.fields['order[%d][column]' % i] = forms.IntegerField(required=False, min_value=0, max_value=5)
            self.fields['order[%d][dir]' % i] = forms.CharField(required=False, choices=(('asc', 'asc'), ('desc', 'desc')))
           
        self.fields['search[regex]' % i] = forms.BooleanField(required=False)
        self.fields['search[value]' % i] = forms.BooleanField(required=False)
   
        draw = forms.IntegerField()
        length = forms.IntegerField()
        start = forms.IntegerField()

Cheers,
Andrea



Tom

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CAFHbX1LcWXQuusg-%2BH8eM63zgv5H6W1-HQY1o%2BCgHm4mOayOCg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Andrea

unread,
Jul 25, 2014, 10:25:58 AM7/25/14
to django...@googlegroups.com
Sorry, the code was a bit of a mess. The following works, although it seems to me that in principle I could think of better solutions, as the GET data is somehow well organized in an array and not plain as it is in my form class.

class DataTablesForm(forms.Form):

    draw = forms.IntegerField()
    length = forms.IntegerField()
    start = forms.IntegerField()
       
    def __init__(self, *args, **kwargs):
        super(DataTablesForm, self).__init__(*args, **kwargs)

        self.fields['_'] = forms.CharField()
           
        for i in range(0, 6):
            self.fields['columns[%d][data]' % i] = forms.CharField(required=False)
            self.fields['columns[%d][name]' % i] = forms.CharField(required=False)
            self.fields['columns[%d][orderable]' % i] = forms.BooleanField(required=False)
            self.fields['columns[%d][search][regex]' % i] = forms.BooleanField(required=False)
            self.fields['columns[%d][search][value]' % i] = forms.CharField(required=False)
            self.fields['columns[%d][searchable]' % i] = forms.BooleanField(required=False)
           
            self.fields['order[%d][column]' % i] = forms.IntegerField(required=False, min_value=0, max_value=5)
            self.fields['order[%d][dir]' % i] = forms.ChoiceField(required=False, choices=(('asc', 'asc'), ('desc', 'desc')))
           
        self.fields['search[regex]'] = forms.BooleanField(required=False)
        self.fields['search[value]'] = forms.BooleanField(required=False)

Thanks for your help,
Andrea

Tom Evans

unread,
Jul 25, 2014, 10:29:04 AM7/25/14
to django...@googlegroups.com
You could do it that way, but no, that is not what I meant.

You have an external library that is producing data in one format. You
want to use that library, without changing the library itself, in
another library (django) that expects a different format.

The interface for inserting information into a Form is the QueryDict.
Start with the QueryDict that django decodes from the request, and
rewrite the key names so that they now match up with the format that
Django allows for forms (and matching your class).

The alternative way is dynamically producing the fields so that you
can create fields with unpythonic names. Personally, I think it is
cleaner to transform the data to match your API than munge the API to
match your data.

Cheers

Tom

Andrea

unread,
Jul 25, 2014, 11:01:48 AM7/25/14
to django...@googlegroups.com
Thanks Tom, now I see your point.
As my API was crafted on the previous version of Datatables, and used only for that purpose, I prefer just to replace it with the new one.
Had I already an API for whatever reason, I see the usefulness and the importance of your approach. I understand the logic, but I'm still not sure how I could code it.

The QueryDict you point out is in my case `request.GET`.

new_request_get = QueryDict(mutable=True)
new_request_get['new_key'] = request.GET['old_key']
# ...
# Set perhaps mutable=False
form = DataTablesForm(new_request_get)

Is what you mean something like that?

Thanks,
Andrea



Cheers

Tom

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.

Tom Evans

unread,
Jul 25, 2014, 11:50:09 AM7/25/14
to django...@googlegroups.com
On Fri, Jul 25, 2014 at 4:00 PM, Andrea <andre...@gmail.com> wrote:
> Thanks Tom, now I see your point.
> As my API was crafted on the previous version of Datatables, and used only
> for that purpose, I prefer just to replace it with the new one.
> Had I already an API for whatever reason, I see the usefulness and the
> importance of your approach. I understand the logic, but I'm still not sure
> how I could code it.
>
> The QueryDict you point out is in my case `request.GET`.
>
> new_request_get = QueryDict(mutable=True)
> new_request_get['new_key'] = request.GET['old_key']
> # ...
> # Set perhaps mutable=False
> form = DataTablesForm(new_request_get)
>
> Is what you mean something like that?
>
> Thanks,
> Andrea

Yep but happening inside the form itself. Eg:

class MyForm(Form):
def __init__(self, *args, **kwargs):
data =kwargs.get('data')
if data:
new_data = QueryDict(mutable=True)
new_data[...] = ....
...
kwargs['data'] = new_data
super(MyForm, self).__init__(*args, **kwargs)

view:

form = MyForm(data=request.POST)

Then, anywhere you use the form it has the logic to process the data
correctly without polluting the view.

Cheers

Tom

Andrea

unread,
Jul 25, 2014, 11:58:05 AM7/25/14
to django...@googlegroups.com
OK, thanks! I won't use it for this specific case, but I'm sure it will be extremely helpful in the future. The logic you've shown can be applied in other different contexts.

Andrea



Cheers

Tom

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
Reply all
Reply to author
Forward
0 new messages