Harry
Harry

Reputation: 13329

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

Upvotes: 4

Views: 3428

Answers (3)

Amyth
Amyth

Reputation: 32959

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.

Upvotes: 8

kgr
kgr

Reputation: 9948

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

Upvotes: 1

nmb.ten
nmb.ten

Reputation: 2228

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

Upvotes: 1

Related Questions