Question

I have a simple resource that I would like perform a DELETE. On success I would like to get the ID of the object that was deleted. As per the docs, always_return_data - Specifies all HTTP methods (except DELETE) should return a serialized form of the data.

http://django-tastypie.readthedocs.org/en/latest/resources.html#always-return-data

class SimpleResource(resources.MongoEngineResource):
    class Meta:
        queryset = Simple.objects.all()
        resource_name = 'simple'
        allowed_methods = ('get', 'put', 'post', 'delete', 'patch')
        always_return_data = True

Question: Is there anyway to serialize data to return the object that was deleted?

Was it helpful?

Solution

Looking at the source and documentation for tastypie, it looks like you'll need to override two functions of ModelResource (which MongoEngineResource inherits):

  1. obj_delete which deletes the object.

  2. delete-detail which is called on a DELETE request and calls obj_delete then returns a 204 No Content or 404 Not Found

I haven't worked with tastypie so this is all from looking at the documentation, but it's at least a starting point. You'll need to do something like this to your class:

class SimpleResource(resources.MongoEngineResource):
    class Meta:
        queryset = Simple.objects.all()
        resource_name = 'simple'
        allowed_methods = ('get', 'put', 'post', 'delete', 'patch')
        always_return_data = True


    def obj_delete(self, bundle, **kwargs):
        try:
            # get an instance of the bundle.obj that will be deleted
            deleted_obj = self.obj_get(bundle=bundle, **kwargs)
        except ObjectDoesNotExist:
            raise NotFound("A model instance matching the provided arguments could not be found.")
        # call the delete, deleting the obj from the database
        super(MongoEngineResource, self).obj_delete(bundle, **kwargs)
        return deleted_obj


    def delete_detail(self, request, **kwargs):
        bundle = Bundle(request=request)

        try:
            # call our obj_delete, storing the deleted_obj we returned
            deleted_obj = self.obj_delete(bundle=bundle, **self.remove_api_resource_names(kwargs))
            # build a new bundle with the deleted obj and return it in a response
            deleted_bundle = self.build_bundle(obj=deleted_obj, request=request)
            deleted_bundle = self.full_dehydrate(deleted_bundle)
            deleted_bundle = self.alter_detail_data_to_serialize(request, deleted_bundle)
            return self.create_response(request, deleted_bundle, response_class=http.HttpNoContent)
        except NotFound:
            return http.HttpNotFound()

OTHER TIPS

you do not need to return the deleted object. You can just update the bundle.obj in obj_delete and then return it to the delete_detail. I am using custom resources and a middleware to run the api, but if you skip on the meta-model thingy it is pretty straight forward.

def obj_delete(self,bundle, **kwargs):
    self.load_user_obj(bundle.request)
    l_instanceId = kwargs['pk']
    try:
        #load the instance
        self.m_objMetaModel.load(l_instanceId,True)

        #do the manipulation on it
        self.m_objMetaModel.REST_IMPL.delete()

        #get an instance back. In my case in the delete I
        #am creating a virtual instance- just an object that 
        #fits the other parts of the api
        bundle.obj = self.m_objMetaModel.instance

        #load the bundle manually
        self.m_objMetaModel.REST_IMPL.reload_data(bundle.obj,bundle.data)

        return bundle
    except Exception as e:
        print(e)
def delete_detail(self, request, **kwargs):
    bundle = Bundle(request=request)

    try:
        # perform the operation returning the recreated bundle
        deleted_bundle = self.obj_delete(bundle=bundle,
                                **self.remove_api_resource_names(kwargs))

        # keep the meta configuration, just to avoid surprises later
        if not self._meta.always_return_data:
            return http.HttpNoContent()
        else:
            #update the bundle, you can skip on the dehydrate if you 
            #are loading the bundle data manually
            deleted_bundle = self.full_dehydrate(deleted_bundle)
            deleted_bundle = self.alter_detail_data_to_serialize(request, 
                                                               deleted_bundle)
            return self.create_response(request, deleted_bundle)
    except NotFound:
            return http.HttpNotFound()

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top