Jquery ajax and Django - post-data arrives malformed - django

I am making a post via Jquery ajax that looks like this:
$.ajax({
type: 'POST',
url: "/sandbox/read_demands/",
data: {
"partner_ref": "PH",
"return_field": ["summary", "details"]
},
success: [read_demands_response],
dataType: 'json'
});
I then recieve the data on the server-side with a simple Django view that only prints request.POST into a log. The data then looks like this:
{u'return_field[]': [u'summary', u'details'], u'partner_ref': [u'PH']}
As you can see, the key 'return_field' has become 'return_field[]' and the value for 'partner_ref' is now a list. What on earth is going on? Am I missing something complected obvious in the jquery post that causes my data to be malformed or is do you think this error comes from somewhere else? I am trying to rule-out different possibilities until I can find the cause of the problem.
This is jquery 1.8.2 and Django 1.4 btw.

The first one is just jQuery being jQuery. For reasons best known to themselves, the makers of jQuery believe that PHP is the only way to write server-side applications, and PHP expects fields that have more than one value to have the [] suffix - so if you don't provide one, it'll add it. You just have to use it like that in Django.
However, the second one is not an error. It's just how a Django QueryDict works: any value can have multiple items, so they'll always be represented as a list. However, request.POST['partner_ref'] will correctly give the single value. And in fact to access both values of the other key, you'll need to do request.POST.getlist('return_field[]').
Edit: as pointed out in the comments, $.ajaxSettings.traditional = true; fixes the jQuery issue.

I've been dealing with the same problem, and found this related question.
How to get an array in Django posted via Ajax
The answer recommends using
request.GET.getlist('data')

Related

Not possible to use shorthand route handlers if RestSerializer is used? (ember-cli-mirage)

I set up a simple Ember Twiddle to show you my error that is occurring when trying to update a model.
It's considerable that I'm using ember-cli-mirage for mocking the data.
According to the docs, I created a shorthand route that should handle the PUT request.
It does, but with the error: Your handler for the url /api/shops/1 threw an error: Cannot convert undefined or null to object
When using the JSONAPISerializer, everything is working with shorthands (mirage/config.js) and I'm able to update models, but in my case I have to use the RESTSerializer with serialized IDs in the responses.
The request payload when I'm sending the model's attrs are without Id at the end of the property name, f.e.:
// attrs object in PUT request
{
name: "Shop 1",
city: "1" // belongsTo relationship,
}
Now Mirage is trying to find those properties on the respective database model that has to be updated, but cannot find it, because in the database it's cityId and not just city...
I also found this issue report and it’s working, but I was hoping I could avoid something like this. As far as I can remember, in previous versions of ember-cli-mirage (v0.1.x) it was also not needed to override the normalize method in the serializer to be able to make use of the RestSerializer with serializedIds…
My question is:
Is there a way to stick to shorthand route handlers only, or do I really have to write a helper or other custom solution only because I have to use the RestSerializer?
That would be really sad, but at least I would know then.
Thanks for your support!
Short answer: it looks like you need the custom serializer for now until the bug fix for it is merged.
Long answer: that issue looks to be an issue that occurred in the 0.2 -> 0.3 upgrade for Mirage, likely because of underlying DB changes made in Mirage. It'll probably get fixed, but for now you'll need to work around it.

Is there any way to render Handlebars templates on server via Backbone in front-end?

edited
This question is in addition to previous Handlebars with Backbone template not rendering problem in which browseser was not rendering forms at all now the problem was solved for the form but returns another error which is possibly also with the rendering.
I have an app with Backbone on front-end and Express in back-end with express-handlebars templates and I was trying to change from Underscore templating to Handlebars while still leaving backbone logic behind. So the way I did it - installing handlebars via Bower and then required it.
app.ContactView = Backbone.View.extend({
//....
template: Handlebars.compile( $('#tmpl-contact').html() ),
//....
});
instead of
app.ContactView = Backbone.View.extend({
//....
template: _.template( $('#tmpl-contact').html() ),
//....
});
But it returns errors and I don't really get what causes them.
When I try to load a page, for example:
http://192.168.33.10:3000/contact/
It doesn't shows any errors in the browser. But if I move to:
http://192.168.33.10:3000/about
which doesn't even have Backbone logic behind it returns an error:
You must pass a string or Handlebars AST to Handlebars.compile. You
passed undefined
Which means that template is compiled before the DOM loads on the page. But my Backbone script is loading after html script e. g. after the {{{body}}} element. Also if there is a problem with an order I should get this error on every, not only when moving to another.
So I think the cause is some kind of a conflict between front-end handlebars and express-handlebars on a server. How to solve this, preferably that templates to be rendered via expHbs instance?
If the only change that you made was:
template: Handlebars.compile( $('#tmpl-contact').html() ),
to:
template: _.template( $('#tmpl-contact').html() ),
it wouldn't cause the problems you're describing. As the error message told you "You passed undefined", and undefined wouldn't have worked with the Underscore code either.
It seems more likely that you changed something else, and that change caused the issue you described. However, without more code (ideally a JS Fiddle) it's hard to say what.
Problem solved by loading each Backbone part as a separate file for its route.

Ember data entity id generation

When new model is created and saved with RESTAdapter its Id property is undefined, because my backend is responsible for id generation. So when I return to grid there is 2 same entities: first - with empty Id (from RESTAdapter cache, I think) and second - with correct Id returned from backend.
Any ideas? Maybe it is posiible to disable RESTAdapter cache?
UPDATE
My code for entity creation.
submit:function () {
var manager = App.store.createRecord(App.Manager, {
firstName:this.get('firstName'),
lastName:this.get('lastName'),
speciality:this.get('speciality')
});
App.store.commit();
this.get('controller').transitionTo('managers');
return false;
}
NEW UPDATE
Thanks to Mike Grassotti hints. Here some details for my issue.
One antity have Id, another have no Id.
If I remove App.store.commit() code, there is no POST to server and only entity without Id will be displayed.
This entity has isLoaded=false and isError=true.
When new model is created and saved with RESTAdapter its Id property is undefined, because my backend is responsible for id generation.
Right, but there is nothing unusual about this - ember expects id generation to be done by the backend.
So when I return to grid there is 2 same entities: first - with empty Id (from RESTAdapter cache, I think) and second - with correct Id returned from backend.
OK. What do you mean by same 2 entities - surely they are different js objects. Try logging each of them to console like this:
console.log(entityOne.toString());
console.log(entityTwo.toString());
Any ideas?
There are many things that could cause this to happen. Sounds like somehow you are creating two new records and saving just one of them. Or could be the API response does not match what ember expects, causing an extra record to get created.
Try to enable logging on your records, then watch console so you can see what's going on as your model is saved. Hopefully this will give you some insight into when/how the extra record is being created.
record.set("stateManager.enableLogging", true)
Inspect browser communication with your api and compare JSON to see if it matches what the ember rest adapter expects.
Post that JSON and the rest of your source code (model definition, etc.) to Stack Overflow, maybe a second set of eyes will help.
Check this post for some other debugging tips: http://www.akshay.cc/blog/2013-02-22-debugging-ember-js-and-ember-data.html
Maybe it is posiible to disable RESTAdapter cache?
RESTAdapter does not maintain a separate cache of model objects. And since you are not trying to do anything special, there should be no need to take a step like that.
Many thanks to Mike Grassotti, I have found an answer to my question.
The good question was
With App.store.commit() back in, what does the JSON response from
server look like?
+1 for that comment.
I can't find any info in ember-data documentation for that, so some links still would be helpful for me. I change the result returned from backend and everything works fine now.
{
"manager": {
"firstName": "test",
"lastName": "test",
"speciality": "test",
"id": "acd325ac-03eb-419e-be8a-d4ac42e8c235"
}
}

How to deal with IE's not encoding URL in django?

In browsers like chrome and firefox, if you type something like this into the address line:
http://mysite.com/q?name=喇叭嘴
they help you encode the url into:
http://mysite.com/?q=%E5%96%87%E5%8F%AD%E5%98%B4
So, in django, you can just use:
request.GET.get('q', '')
to get the value '喇叭嘴'.
However, this thing does not happen in IE(msie, thanks). That's why we keep on getting ��� instead.
With ajax handling, I can just use JavaScript encodeURI() Function to work around with it. However, triggering it every time is such a pain.
Is there any way to handle the issue in the backend?

How to catch and view the JSON response?

I have this following view which I get data from a model and thereafter serialize it into JSON.
views.py
def polling(request):
if request.is_ajax():
data = UserReview.objects.filter(movie_id=request.GET['m_id'])
serializers.serialize('json', data)
return HttpResponse(data, mimetype='application/json')
else:
raise Http404
At the client side I want to show this content now. I'm using jQuery's function getJSON to archive this. It won't show anything, and the setTimeout doesn't work as well. But I get a response when I debug it with firebug, it however doesn't call the alert() function to view the data. I've been trying to figure out what the problem could be for some time now. So I wonder if there's something wrong with my script?
javascript
function polling() {
$.getJSON( "/polling/",
{m_id: {{movie_info.id}} },
function(data) {
alert(data)
setTimeout(polling, 5000)
});
};
Some general methods that will help you find out what is wrong.
Use console.log very liberally on the front end to make sure everything is going as planned
http://api.jquery.com/jQuery.ajax/ Callback functions as suggested in a comment, make sure you at least logg an error
https://docs.djangoproject.com/en/dev/topics/logging/ set up a debug logger, make sure that you can see what is going on and what django is actually returning as json.
http://docs.python.org/library/pdb.html Better yet drop this badboy anywhere in your code and MAKE SURE that everything is going the right way. If your success is not being called ont the front end i bet the error is in django! find out where.
You can view the errors in the HTML tab in firebug if debug=True or you can just request /polling/ through your browser and view the django error screen.
using some or any of these should put you in a fine place to solve your problem django dev server makes it an absolute ease to breeze through these errors please do some research and find out the many many debug tools made available to you!
I'm new to all of this but have you tried to use.
$.ajax
({
url: "/Build/AllStatuses",
dataType: 'json',
success: function (buildstatuses)
This is how I used to call my json and it seems to work.