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)
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.