def patch_detail(self, request, **kwargs): request = convert_post_to_patch(request) try: obj = self.cached_obj_get(request=request, **self.remove_api_resource_names(kwargs)) except ObjectDoesNotExist: return http.HttpNotFound() except MultipleObjectsReturned: return http.HttpMultipleChoices('More than one resource' 'is found at this URI.') bundle = self.build_bundle(obj=obj, request=request) bundle = self.full_dehydrate(bundle) bundle = self.alter_detail_data_to_serialize(request, bundle) # Now update the bundle in-place. deserialized = self.deserialize(request, request.raw_post_data, format=request.META.get( 'CONTENT_TYPE', 'application/json')) # In case of a patch modification, we need to store # the initial values for the given object to check # the Etag header. request.initial_etag = bundle.obj.etag return self.create_patch_response(request, bundle, deserialized)
def patch_detail(self, request, **kwargs): request = convert_post_to_patch(request) try: obj = self.cached_obj_get( request=request, **self.remove_api_resource_names(kwargs)) except ObjectDoesNotExist: return http.HttpNotFound() except MultipleObjectsReturned: return http.HttpMultipleChoices('More than one resource' 'is found at this URI.') bundle = self.build_bundle(obj=obj, request=request) bundle = self.full_dehydrate(bundle) bundle = self.alter_detail_data_to_serialize(request, bundle) # Now update the bundle in-place. deserialized = self.deserialize( request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json')) # In case of a patch modification, we need to store # the initial values for the given object to check # the Etag header. request.initial_etag = bundle.obj.etag return self.create_patch_response(request, bundle, deserialized)
def patch_list(self, request, **kwargs): request = convert_post_to_patch(request) deserialized = self.deserialize(request, request.body, format=request.META.get( 'CONTENT_TYPE', 'application/json')) for data in deserialized["objects"]: data = self.alter_deserialized_detail_data(request, data) bundle = self.build_bundle(data=dict_strip_unicode_keys(data)) bundle.request.user = request.user bundle.request.META['REMOTE_ADDR'] = request.META.get( 'REMOTE_ADDR', '0.0.0.0') bundle.request.META['HTTP_USER_AGENT'] = request.META.get( 'HTTP_USER_AGENT', 'unknown') self.obj_create(bundle, request=request) response_data = { 'points': self.dehydrate_points(bundle), 'badges': self.dehydrate_badges(bundle), 'scoring': self.dehydrate_scoring(bundle), 'badging': self.dehydrate_badging(bundle), 'metadata': self.dehydrate_metadata(bundle), 'course_points': self.dehydrate_course_points(bundle), } response = HttpResponse(content=json.dumps(response_data), content_type="application/json; charset=utf-8") return response
def patch_list(self, request=None, **kwargs): """ Exactly copied from https://github.com/toastdriven/django-tastypie/blob/v0.9.14/tastypie/resources.py#L1466 (BSD licensed) and modified to pass the kwargs to `obj_create` and support only create method """ request = convert_post_to_patch(request) deserialized = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json')) collection_name = self._meta.collection_name if collection_name not in deserialized: raise BadRequest("Invalid data sent: missing '%s'" % collection_name) if len(deserialized[collection_name]) and 'put' not in self._meta.detail_allowed_methods: raise ImmediateHttpResponse(response=http.HttpMethodNotAllowed()) bundles_seen = [] status = http.HttpAccepted for data in deserialized[collection_name]: data = self.alter_deserialized_detail_data(request, data) bundle = self.build_bundle(data=dict_strip_unicode_keys(data), request=request) try: self.obj_create(bundle=bundle, **self.remove_api_resource_names(kwargs)) except AssertionError as ex: status = http.HttpBadRequest bundle.data['_id'] = ex.message bundles_seen.append(bundle) to_be_serialized = [bundle.data['_id'] for bundle in bundles_seen] return self.create_response(request, to_be_serialized, response_class=status)
def patch_list(self, request=None, **kwargs): """ Exactly copied from https://github.com/toastdriven/django-tastypie/blob/v0.9.14/tastypie/resources.py#L1466 (BSD licensed) and modified to pass the kwargs to `obj_create` and support only create method """ request = convert_post_to_patch(request) deserialized = self.deserialize(request, request.raw_post_data, format=request.META.get('CONTENT_TYPE', 'application/json')) collection_name = self._meta.collection_name if collection_name not in deserialized: raise BadRequest("Invalid data sent: missing '%s'" % collection_name) if len(deserialized[collection_name]) and 'put' not in self._meta.detail_allowed_methods: raise ImmediateHttpResponse(response=http.HttpMethodNotAllowed()) bundles_seen = [] status = http.HttpAccepted for data in deserialized[collection_name]: data = self.alter_deserialized_detail_data(request, data) bundle = self.build_bundle(data=dict_strip_unicode_keys(data), request=request) try: self.obj_create(bundle=bundle, **self.remove_api_resource_names(kwargs)) except AssertionError as ex: status = http.HttpBadRequest bundle.data['_id'] = ex.message bundles_seen.append(bundle) to_be_serialized = [bundle.data['_id'] for bundle in bundles_seen] return self.create_response(request, to_be_serialized, response_class=status)
def patch_list(self, request, **kwargs): request = convert_post_to_patch(request) deserialized = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json')) for data in deserialized.get("objects"): data = self.alter_deserialized_detail_data(request, data) bundle = self.build_bundle(data=dict_strip_unicode_keys(data)) bundle.request.user = request.user bundle.request.META['REMOTE_ADDR'] = request.META.get('REMOTE_ADDR', api.DEFAULT_IP_ADDRESS) bundle.request.META['HTTP_USER_AGENT'] = request.META.get('HTTP_USER_AGENT', 'unknown') # check UUID not already submitted if 'data' in bundle.data: json_data = json.loads(bundle.data['data']) if 'uuid' in json_data: uuids = Tracker.objects.filter(uuid=json_data['uuid']) if uuids.count() == 0: self.obj_create(bundle, request=request) else: self.obj_create(bundle, request=request) else: self.obj_create(bundle, request=request) response_data = {'points': self.dehydrate_points(bundle), 'badges': self.dehydrate_badges(bundle), 'scoring': self.dehydrate_scoring(bundle), 'badging': self.dehydrate_badging(bundle), 'metadata': self.dehydrate_metadata(bundle), 'course_points': self.dehydrate_course_points(bundle), } response = HttpResponse(content=json.dumps(response_data), content_type="application/json; charset=utf-8") return response
def patch_list(self, request, **kwargs): request = convert_post_to_patch(request) deserialized = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json')) bundle = self.build_bundle(data=deserialized, request=request) return self.obj_update(bundle)
def patch_detail(self, request, **kwargs): pk = kwargs.get("pk") request = convert_post_to_patch(request) self.authorized_update_detail( Spirit.objects.filter(pk=pk), self.build_bundle(request=request) ) form = PatchForm( request, get_object_or_404(Spirit, pk=pk), self.deserialize( request, request.body, format=request.META.get("CONTENT_TYPE", "application/json") ) ) if form.is_valid(): form.save() return self.create_response(request, "", status=202) raise BadRequest(form.errors.as_text())
def patch_list(self, request, **kwargs): request = convert_post_to_patch(request) deserialized = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json')) for data in deserialized["objects"]: data = self.alter_deserialized_detail_data(request, data) bundle = self.build_bundle(data=dict_strip_unicode_keys(data)) bundle.request.user = request.user bundle.request.META['REMOTE_ADDR'] = request.META.get('REMOTE_ADDR', api.DEFAULT_IP_ADDRESS) bundle.request.META['HTTP_USER_AGENT'] = request.META.get('HTTP_USER_AGENT', 'unknown') # check UUID not already submitted if 'data' in bundle.data: json_data = json.loads(bundle.data['data']) if 'uuid' in json_data: uuids = Tracker.objects.filter(uuid=json_data['uuid']) if uuids.count() == 0: self.obj_create(bundle, request=request) else: self.obj_create(bundle, request=request) else: self.obj_create(bundle, request=request) response_data = {'points': self.dehydrate_points(bundle), 'badges': self.dehydrate_badges(bundle), 'scoring': self.dehydrate_scoring(bundle), 'badging': self.dehydrate_badging(bundle), 'metadata': self.dehydrate_metadata(bundle), 'course_points': self.dehydrate_course_points(bundle), } response = HttpResponse(content=json.dumps(response_data), content_type="application/json; charset=utf-8") return response
def patch_detail(self, request, **kwargs): """ Updates a resource in-place. Calls ``obj_update``. If the resource is updated, return ``HttpAccepted`` (202 Accepted). If the resource did not exist, return ``HttpNotFound`` (404 Not Found). """ request = convert_post_to_patch(request) basic_bundle = self.build_bundle(request=request) # We want to be able to validate the update, but we can't just pass # the partial data into the validator since all data needs to be # present. Instead, we basically simulate a PUT by pulling out the # original data and updating it in-place. # So first pull out the original object. This is essentially # ``get_detail``. try: obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs)) except ObjectDoesNotExist: return http.HttpNotFound() except MultipleObjectsReturned: return http.HttpMultipleChoices( "More than one resource is found at this URI.") self.post_obj_get(obj) bundle = self.build_bundle(obj=obj, request=request) bundle = self.full_dehydrate(bundle) bundle = self.alter_detail_data_to_serialize(request, bundle) # Now update the bundle in-place. deserialized = self.deserialize(request, request.body, format=request.META.get( 'CONTENT_TYPE', 'application/json')) self.update_in_place(request, bundle, deserialized) # TODO: Check if this try/except is neccessary #try: # self.update_in_place(request, bundle, deserialized) #except ObjectDoesNotExist: # return http.HttpNotFound() # if not self._meta.always_return_data: return http.HttpAccepted() else: bundle = self.full_dehydrate(bundle) bundle = self.alter_detail_data_to_serialize(request, bundle) return self.create_response(request, bundle, response_class=http.HttpAccepted)
def patch_list(self,request,**kwargs): request = convert_post_to_patch(request) deserialized = self.deserialize(request, request.raw_post_data, format=request.META.get('CONTENT_TYPE', 'application/json')) for data in deserialized["objects"]: data = self.alter_deserialized_detail_data(request, data) bundle = self.build_bundle(data=dict_strip_unicode_keys(data)) bundle.request.user = request.user bundle.request.META['REMOTE_ADDR'] = request.META.get('REMOTE_ADDR','0.0.0.0') bundle.request.META['HTTP_USER_AGENT'] = request.META.get('HTTP_USER_AGENT','unknown') self.obj_create(bundle, request=request) response_data = {'points': self.dehydrate_points(bundle),'badges':self.dehydrate_badges(bundle)} response = HttpResponse(content=json.dumps(response_data),content_type="application/json; charset=utf-8") return response
def patch_list(self, request, **kwargs): response = super(SSEMixin, self).patch_list(request, **kwargs) patch = convert_post_to_patch(request) data = self.deserialize(patch, patch.body) try: objects = data.get('objects', []) container = Container.objects.get(pk=data.get('container_id')) notify.delay(objects, type="json", container=container, user=request.user) except Exception as e: logger.error("Impossible to create notification {}, {}".format(data, e)) return response
def patch_detail(self, request, **kwargs): """ Updates a resource in-place. Calls ``obj_update``. If the resource is updated, return ``HttpAccepted`` (202 Accepted). If the resource did not exist, return ``HttpNotFound`` (404 Not Found). """ request = convert_post_to_patch(request) basic_bundle = self.build_bundle(request=request) # We want to be able to validate the update, but we can't just pass # the partial data into the validator since all data needs to be # present. Instead, we basically simulate a PUT by pulling out the # original data and updating it in-place. # So first pull out the original object. This is essentially # ``get_detail``. try: obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs)) except ObjectDoesNotExist: return http.HttpNotFound() except MultipleObjectsReturned: return http.HttpMultipleChoices("More than one resource is found at this URI.") self.post_obj_get(obj) bundle = self.build_bundle(obj=obj, request=request) bundle = self.full_dehydrate(bundle) bundle = self.alter_detail_data_to_serialize(request, bundle) # Now update the bundle in-place. deserialized = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json')) self.update_in_place(request, bundle, deserialized) # TODO: Check if this try/except is neccessary #try: # self.update_in_place(request, bundle, deserialized) #except ObjectDoesNotExist: # return http.HttpNotFound() # if not self._meta.always_return_data: return http.HttpAccepted() else: bundle = self.full_dehydrate(bundle) bundle = self.alter_detail_data_to_serialize(request, bundle) return self.create_response(request, bundle, response_class=http.HttpAccepted)
def patch_detail(self, request, **kwargs): request = convert_post_to_patch(request) basic_bundle = self.build_bundle(request=request) # We want to be able to validate the update, but we can't just pass # the partial data into the validator since all data needs to be # present. Instead, we basically simulate a PUT by pulling out the # original data and updating it in-place. # So first pull out the original object. This is essentially # ``get_detail``. try: obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs)) except ObjectDoesNotExist: return http.HttpNotFound() except MultipleObjectsReturned: return http.HttpMultipleChoices( "More than one resource is found at this URI.") bundle = self.build_bundle(obj=obj, request=request) bundle = self.full_dehydrate(bundle) bundle = self.alter_detail_data_to_serialize(request, bundle) # Now update the bundle in-place. deserialized = self.deserialize(request, request.body, format=request.META.get( 'CONTENT_TYPE', 'application/json')) #print(request.user) self.update_application(request, deserialized) #self.update_in_place(request, bundle, deserialized) #print(deserialized) #print(request) if not self._meta.always_return_data: return http.HttpAccepted() else: # Invalidate prefetched_objects_cache for bundled object # because we might have changed a prefetched field bundle.obj._prefetched_objects_cache = {} bundle = self.full_dehydrate(bundle) bundle = self.alter_detail_data_to_serialize(request, bundle) return self.create_response(request, bundle, response_class=http.HttpAccepted)
def patch_list(self, request, **kwargs): request = convert_post_to_patch(request) deserialized = self.deserialize( request, request.body, format=request.META.get("CONTENT_TYPE", "application/json") ) for data in deserialized["objects"]: data = self.alter_deserialized_detail_data(request, data) bundle = self.build_bundle(data=dict_strip_unicode_keys(data)) bundle.request.user = request.user bundle.request.META["REMOTE_ADDR"] = request.META.get("REMOTE_ADDR", "0.0.0.0") bundle.request.META["HTTP_USER_AGENT"] = request.META.get("HTTP_USER_AGENT", "unknown") self.obj_create(bundle, request=request) response_data = { "points": self.dehydrate_points(bundle), "badges": self.dehydrate_badges(bundle), "scoring": self.dehydrate_scoring(bundle), "badging": self.dehydrate_badging(bundle), "metadata": self.dehydrate_metadata(bundle), "course_points": self.dehydrate_course_points(bundle), } response = HttpResponse(content=json.dumps(response_data), content_type="application/json; charset=utf-8") return response
def patch_list(self, request, **kwargs): """ Updates a collection in-place. The exact behavior of ``PATCH`` to a list resource is still the matter of some debate in REST circles, and the ``PATCH`` RFC isn't standard. So the behavior this method implements (described below) is something of a stab in the dark. It's mostly cribbed from GData, with a smattering of ActiveResource-isms and maybe even an original idea or two. The ``PATCH`` format is one that's similar to the response returned from a ``GET`` on a list resource:: { "objects": [{object}, {object}, ...], "deleted_objects": ["URI", "URI", "URI", ...], } For each object in ``objects``: * If the dict does not have a ``resource_uri`` key then the item is considered "new" and is handled like a ``POST`` to the resource list. * If the dict has a ``resource_uri`` key and the ``resource_uri`` refers to an existing resource then the item is a update; it's treated like a ``PATCH`` to the corresponding resource detail. * If the dict has a ``resource_uri`` but the resource *doesn't* exist, then this is considered to be a create-via-``PUT``. Each entry in ``deleted_objects`` referes to a resource URI of an existing resource to be deleted; each is handled like a ``DELETE`` to the relevent resource. In any case: * If there's a resource URI it *must* refer to a resource of this type. It's an error to include a URI of a different resource. * ``PATCH`` is all or nothing. If a single sub-operation fails, the entire request will fail and all resources will be rolled back. * For ``PATCH`` to work, you **must** have ``put`` in your :ref:`detail-allowed-methods` setting. * To delete objects via ``deleted_objects`` in a ``PATCH`` request you **must** have ``delete`` in your :ref:`detail-allowed-methods` setting. Substitute appropriate names for ``objects`` and ``deleted_objects`` if ``Meta.collection_name`` is set to something other than ``objects`` (default). """ request = convert_post_to_patch(request) deserialized = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json')) collection_name = self._meta.collection_name deleted_collection_name = 'deleted_%s' % collection_name if collection_name not in deserialized: raise BadRequest("Invalid data sent: missing '%s'" % collection_name) if len(deserialized[collection_name]) and 'put' not in self._meta.detail_allowed_methods: raise ImmediateHttpResponse(response=http.HttpMethodNotAllowed()) bulk_commands = [] bundles_seen = [] def index(bundle, command='index'): command = {command:{'_id':bundle.data["_id"]}} bulk_commands.append(command) command = bundle.obj bulk_commands.append(command) for data in deserialized[collection_name]: # If there's a resource_uri then this is either an # update-in-place or a create-via-PUT. if "resource_uri" in data: try: uri = data.pop('resource_uri') obj = self.get_via_uri(uri, request=request) # The object does exist, so this is an update-in-place. bundle = self.build_bundle(obj=obj['_source'], request=request) bundle.data.update(data) bundle = self.full_hydrate(bundle) bulk_commands.append({'update':{'_id':bundle.data["_id"]}}) bulk_commands.append({'doc':bundle.obj}) except (ObjectDoesNotExist, MultipleObjectsReturned): # The object referenced by resource_uri doesn't exist, # so this is a create-by-PUT equivalent. data = self.alter_deserialized_detail_data(request, data) bundle = self.build_bundle(data=dict_strip_unicode_keys(data), request=request) #self.obj_create(bundle=bundle) bundle = self.full_hydrate(bundle) index(bundle) else: # There's no resource URI, so this is a create call just # like a POST to the list resource. data = self.alter_deserialized_detail_data(request, data) bundle = self.build_bundle(data=dict_strip_unicode_keys(data), request=request) #self.obj_create(bundle=bundle) bundle = self.full_hydrate(bundle) index(bundle) bundles_seen.append(bundle) deleted_collection = deserialized.get(deleted_collection_name, []) if deleted_collection: if 'delete' not in self._meta.detail_allowed_methods: raise ImmediateHttpResponse(response=http.HttpMethodNotAllowed()) for uri in deleted_collection: obj = self.get_via_uri(uri, request=request) bundle = self.build_bundle(obj=obj['_source'], request=request) #self.obj_delete(bundle=bundle) command = {"delete":{'_id':bundle['pk']}} bulk_commands.append(command) if len(bulk_commands): try: result = self.client.bulk(bulk_commands, refresh=True, index=self._meta.index, doc_type=self._meta.doc_type) except Exception, exc: response = http.HttpBadRequest(str(exc), content_type="text/plain") raise ImmediateHttpResponse(response) else: if not self._meta.always_return_data: return http.HttpAccepted(json.dumps(result)) else: to_be_serialized = {} to_be_serialized['objects'] = [self.full_dehydrate(bundle, for_list=True) for bundle in bundles_seen] to_be_serialized = self.alter_list_data_to_serialize(request, to_be_serialized) return self.create_response(request, to_be_serialized, response_class=http.HttpAccepted)
def patch_list(self, request, **kwargs): """Override of the default to make the allowed methods map better. Mainly makes delete depend on delete (already happend). Makes creation depend on post, full update/create with URI depend on put and update existing depend on patch - which isn't a method at all. """ request = convert_post_to_patch(request) if django.VERSION >= (1, 4): body = request.body else: body = request.raw_post_data deserialized = self.deserialize(request, body, format=request.META.get('CONTENT_TYPE', 'application/json')) collection_name = self._meta.collection_name deleted_collection_name = 'deleted_%s' % collection_name if collection_name not in deserialized: raise BadRequest("Invalid data sent: missing '%s'" % collection_name) #if len(deserialized[collection_name]) and 'put' not in self._meta.detail_allowed_methods: # raise ImmediateHttpResponse(response=http.HttpMethodNotAllowed()) bundles_seen = [] for data in deserialized[collection_name]: # If there's a resource_uri then this is either an # update-in-place or a create-via-PUT. if "resource_uri" in data: uri = data.pop('resource_uri') try: obj = self.get_via_uri(uri, request=request) # The object does exist, so this is an update-in-place. if 'patch' not in self._meta.detail_allowed_methods: raise ImmediateHttpResponse(response=http.HttpMethodNotAllowed()) bundle = self.build_bundle(obj=obj, request=request) bundle = self.full_dehydrate(bundle, for_list=True) bundle = self.alter_detail_data_to_serialize(request, bundle) self.update_in_place(request, bundle, data) except (ObjectDoesNotExist, MultipleObjectsReturned): # The object referenced by resource_uri doesn't exist, # so this is a create-by-PUT equivalent. if 'put' not in self._meta.detail_allowed_methods: raise ImmediateHttpResponse(response=http.HttpMethodNotAllowed()) data = self.alter_deserialized_detail_data(request, data) bundle = self.build_bundle(data=dict_strip_unicode_keys(data), request=request) self.obj_create(bundle=bundle) else: # There's no resource URI, so this is a create call just # like a POST to the list resource. if 'post' not in self._meta.detail_allowed_methods: raise ImmediateHttpResponse(response=http.HttpMethodNotAllowed()) data = self.alter_deserialized_detail_data(request, data) bundle = self.build_bundle(data=dict_strip_unicode_keys(data), request=request) self.obj_create(bundle=bundle) bundles_seen.append(bundle) deleted_collection = deserialized.get(deleted_collection_name, []) if deleted_collection: if 'delete' not in self._meta.detail_allowed_methods: raise ImmediateHttpResponse(response=http.HttpMethodNotAllowed()) for uri in deleted_collection: obj = self.get_via_uri(uri, request=request) bundle = self.build_bundle(obj=obj, request=request) self.obj_delete(bundle=bundle) if not self._meta.always_return_data: return http.HttpAccepted() else: to_be_serialized = {} to_be_serialized['objects'] = [self.full_dehydrate(bundle, for_list=True) for bundle in bundles_seen] to_be_serialized = self.alter_list_data_to_serialize(request, to_be_serialized) return self.create_response(request, to_be_serialized, response_class=http.HttpAccepted)