How should I POST and serialize and array of arrays with DRF? - django

I'm having an issue POST-ing a JSON object that contains and array of arrays and deserializing it using Django Rest Framework.
The idea here is that there can be a dynamic number of players (players: 2) and a list of lists/array of arrays of weapons that the players have (player_weapons [[], []]).
//javascript on client
var post_data = {
players: 2,
player_weapons: [
["sword", "shield"],
["mace", "slingshot"],
]};
var results = jQuery.post( url, post_data );
#serializers.py
class GameSerializer(serializers.Serializer):
players = serializers.IntegerField(min_value=1)
player_weapons = serializers.ListField(
child=serializers.ListField(
child=serializers.CharField(min_length=1, allow_blank=True),
min_length=0,
required=False),
min_length=0,
required=False
)
The request.POST I get is:
<QueryDict: {'runs': ['1000'], 'additional_players': ['2'],
'player_weapons': ['sword,shield', 'mace,slingshot']}>
What's really weird is that when I do request.POST['player_weapons'] I get:
mace,slingshot
whereas I'm expecting/hoping to get:
[['sword', 'shield'], ['mace', 'slingshot']]
Any help on how I should be structuring the POST and handling it in DRF would be awesome.

Thanks to RishiG for the help here.
Problem was that I wasn't specifying the contentType in the request. I slightly modified it to use jQuery's ajax request:
var posting = jQuery.ajax({
url: url,
type: "POST",
data: JSON.stringify(post_data),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function(){
}
});

Related

DJANGO POST GET not working after i18n translation

I have multiple POST requests from my template for example:
$.ajax({
url: '/apply_payment',
type: 'POST',
data: {
basket: JSON.stringify(basket),
key: $('#key_input').val(),
csrfmiddlewaretoken: CSRF_TOKEN
},
dataType: 'json',
success: function (data) {
$("#key_input").val("");
},
...
I read in the basket data in a view.py like this:
basket = request.POST.get('basket', '')
In the urls.py I have these urls in the form of:
path('apply_payment', entrance_api.apply_payment, name='apply_payment'),
Now lately I added i18n_patterns into the URLs, and translated all of my pages, however the AJAX calls stopped working. I guess it is becase the URLs are dynamically changing between selected languages, but I might be wrong.
For example the shows basket variable is always None in the view now. How can I fix this?
From my experience, I had to prepend a language code to the POST request URL:
$.ajax({
url: '/en/apply_payment', // prepend a language code or even better: use window.location.href
type: 'POST',
data: {
basket: JSON.stringify(basket),
key: $('#key_input').val(),
csrfmiddlewaretoken: CSRF_TOKEN
},
dataType: 'json',
success: function (data) {
$("#key_input").val("");
},

Coldfusion <cfsavecontent> variable displays correctly on page but does not save correctly to the DB

I have AJAX writing a result to <span id="response"></span>, which displays as expected. But, I need to convert to a CF variable so I can write the content to the database. Using
<cfsavecontent variable="JSONResponse"><span id="response"></span></cfsavecontent>
allows me to display the new JSONResponse variable on the page correctly, but when I take the same varible and write it to the database, it writes the <span id="response"></span> tag into the table - not the actual content. Does anyone have any suggestions? Thanks
Thanks #GSR & #Dan - I managed to work out a solution by forwarding on to a CFM page that writes to the DB, via another nested ajax post, based upon the response:
var postData = {username: "user#company.com", password: "Ruu3992032!883jj22uje"};
var ajaxResponse = $.ajax({
type: "post",
url: "https://api.company.com/v1/authenticate",
contentType: "application/json",
data: JSON.stringify( postData )
})
// When the response comes back, forward on to another cfm page with insert statement.
ajaxResponse.then(
function( apiResponse ){
$.ajax({
type: "post",
url: "WriteToDB.cfm",
data: jQuery.param({ payload: JSON.stringify( apiResponse ) }) ,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
})
}
);

Using ember data to save multiple records via post

Does anyone know of any working examples of overriding ember-data's DS.Adapter to save all records at once?
I'd like to stringify my entire array of records and send them to my server. I don't have much flexibility on the server to use anything but the existing API which is just a perl CGI script. Any help in the right direction would be appreciated.
What I did was iterate over the ember-data models, serialized them, saved them into a json object that matched server requirements, and executed post request.
var identifiedResponse = []
this.store.filter(key, function (record) {
return !!record.get('name')
}).then(function(resp) {
identifiedResponse.push(item.serialize())
})
jQuery.ajax({
url: url,
type: "POST",
data: identifiedResponse,
contentType: "application/json",
dataType: 'json',
xhrFields: {
withCredentials: true
}
})

Why does my Django request.method does not match POST

$.ajax({
type :'GET',
url : geturl(a),
// type: $(this).attr('method'),
dataType : 'json',
views.py:
if request.method=="POST":
if request.POST.get('monyrsubmit'):
monthform=MonthForm(request.POST)
if monthform.is_valid():
selected_month=monthform.cleaned_data["Month"]
selected_year=monthform.cleaned_data["Year"]
print selected_month
print selected_year
can i have both GET and POST requests in the type field of ajax. im using a form and only when the submit button is clicked im trying to display information based on the data submitted. if request.POST.get('monyrsubmit') does not work.
Help will be appreciated
It's very simple. You have to abstract the events.
function event_page_load() {
function ajax_request('GET')
}
function click_submit_button() {
function ajax_request('POST')
}
function ajax_request(type) {
$.ajax({
type : type,
......
......
})
}
You can also consider the follwoign general guidelines.
GET and POST should be used based on the type of the request to the server
- If you are reading the existing data(without modification) from the server, use GET
- if you are writing/modifying any data in the server, use POST
in jQuery, you can use these simple methods.
For GET requests
$.get(
url,
{param1: "value1", param2: "value2"},
function(responseText){
// todo ;
},
"html"
);
for POST requests
$.post(
url,
{param1: "value1", param2: "value2"},
function(responseText){
// todo ;
},
"html"
);
Make sure that you have disable the browser caching.
$.ajaxSetup ({
cache: false
});
In django side, you can use request.is_ajax() method to verify the ajax call and you can filter based on request.method property.
You can refer all the possible usages of AJAX with Djano at https://github.com/sivaa/django-jquery-ajax-exmaples

Tastypie ajax POST obj_create - How to return json

Im sending a POST that creates a new User, and that works.
My question is how do I get back for example the pk of the created user to the ajax response?
$.ajax({
url: 'http://localhost:8080/api/v1/create/user/',
type: 'POST',
contentType: 'application/json',
data: '{"uuid": "12345"}',
dataType: 'json',
processData: false,
success: function (r) {
console.log(r)
},
});
def obj_create(self, bundle, request=None, **kwargs):
try:
user = User.objects.create_user(bundle.data['uuid'],'1')
user.save()
except:
pass
return bundle
you can set always_return_data=True within your UserResource's Meta and on POST and PUT request it will return the created object back.
From the docs
always_return_data
Specifies all HTTP methods (except DELETE) should return a serialized form of the data. Default is False.
If False, HttpNoContent (204) is returned on POST/PUT with an empty body & a Location header of where to request the full resource.
If True, HttpAccepted (202) is returned on POST/PUT with a body containing all the data in a serialized form.
Each resource has dehydrate method. You can use it to add any data to response. Here are the docs - http://django-tastypie.readthedocs.org/en/latest/cookbook.html#adding-custom-values
You could either use the Location header (set by Tastypie by default) or you could try to make Tastypie send the newly created entity back. I believe the first one is simpler. You may also take a look at related SO question: Is it ok by REST to return content after POST?
First you need to slightly modify jQuery XHR objects,
// Required for reading Location header of POST responses.
var _super = $.ajaxSettings.xhr;
$.ajaxSetup({
xhr: function () {
var xhr = _super();
var getAllResponseHeaders = xhr.getAllResponseHeaders;
xhr.getAllResponseHeaders = function () {
var allHeaders = getAllResponseHeaders.call(xhr);
if (allHeaders) {
return allHeaders;
}
allHeaders = "";
$(["Cache-Control", "Content-Language", "Content-Type", "Expires", "Last-Modified", "Pragma", "Location"]).each(function (i, header_name) {
if (xhr.getResponseHeader(header_name)) {
allHeaders += header_name + ": " + xhr.getResponseHeader(header_name) + "\n";
}
});
return allHeaders;
};
return xhr;
}
});
This is required because (after jQuery $.ajax docs):
At present, due to a bug in Firefox where .getAllResponseHeaders() returns the empty string although .getResponseHeader('Content-Type') returns a non-empty string, automatically decoding JSON CORS responses in Firefox with jQuery is not supported.
A workaround to this is possible by overriding jQuery.ajaxSettings.xhr as follows:
Then you can read the header in the successCallback, like so:
successCallback: errorAwareCall(function (data, t, textStatus, XMLHttpRequest) {
var loc = XMLHttpRequest.getAllResponseHeaders();
var pk = parseInt(loc.match(/\/(\d+)(\/)*/)[1]);
// Do something with the PK
})