Search code examples
jquerypythondjangopostdjango-piston

django Piston Post Request Change strings to lists


I have a simple Django-Piston Handler that creates a new instance of a model and saves it.

From the client, I am posting using Javascript Objects and JQuery.post.

Upon inspecting the data with Firebug, the post string looks like this:

classification=&organization=&title=Formatting+Test+7&description=test&created_by=created_on=&last_modified=&csrfmiddlewaretoken=a8352bb51f88c271119a81228a5c291f

As you can see, only title, description, and csrfmiddlewaretoken are set.

Inside the Piston Handler, at the top of the create method before any other code is run, I print out the request.POST:

print 'POST:', request.POST

Which prints the following in the Django Dev Server output:

POST: <QueryDict: {u'description': [u'test'], u'classification': [u''], u'title': [u'Formatting Test 7'], u'created_by': [u''], u'created_on': [u''], u'last_modified': [u''], u'organization': [u''], u'csrfmiddlewaretoken': [u'a8352bb51f88c271119a81228a5c291f']}>

As you can see, all of the data is in lists now. When I save the data using a Django Form, it converts the list to a string and when the data shows up on the client, instead of "Formatting Test 7", it displays "[u'Formatting Test 7']".

Googling doesn't seem to return anyone with the same problem, and I have been using Piston for over 6 months and I have never seen an error like this before.

EDIT: As JPIC said, the error I thought I was experiencing was not an error, but by design. My problem was in extending the data in the QuerySet before I used it with a Django Form.

The Wrong Way:

some_initial_data = {
    'created_by': creator.pk, 
    'organization': org.pk,
    'classification': 7
} 
post = dict(request.POST)
post.update(some_initial_data)
form = MyModelForm(post)

The Right Way:

As described in the update method for QueryDict: https://docs.djangoproject.com/en/1.3/ref/request-response/#querydict-objects

some_initial_data = {
    'created_by': creator.pk,
    'organization': org.pk,
    'classification': 7
}
post = request.POST.copy()
post.update(initial_data)
form = MyModelForm(post)

Solution

  • It is not an error, your data has always been in such a list, it is a design decision from Django. Whatever code is accessing the QueryDict instance and gets list values otherwise than with the getlist() method is using QueryDict wrong.

    QueryDict allows multiple values for a key ie.: foo=bar&foo=test your QueryDict will be like {u'foo': [u'bar', u'test']}.

    Example with ?foo=bar&foo=test&x=y:

    ipdb> request.GET
    <QueryDict: {u'x': [u'y'], u'foo': [u'bar', u'test']}>
    ipdb> request.GET['x']
    u'y'
    ipdb> request.GET.getlist('x')
    [u'y']
    ipdb> request.GET['foo']
    u'test'
    ipdb> request.GET.getlist('foo')
    [u'bar', u'test']
    

    As you can see, QueryDict is a dict of lists which won't resort to the actual lists by default: it will act like a normal dict. So if some code is getting the list then it's using the QueryDict wrong.

    One thing worth mentionning is that if you want to use $.post(url, {'foo':['bar', 'test']}) then you will need to call $.ajaxSettings.traditional = true !

    This is useful for example with checkboxes or multiple-selects. Correct me if I'm wrong but this is standard, and the PHP way foo[]=bar&foo[]=test is not standard.