Beispiel #1
0
    def obj_delete(self, bundle, **kwargs):
        obj = kwargs.pop('_obj', None)

        if not getattr(obj, 'pk', None):
            try:
                obj = self.obj_get(bundle=bundle, **kwargs)
            except (queryset.DoesNotExist, exceptions.ObjectDoesNotExist):
                raise tastypie_exceptions.NotFound(
                    "A document instance matching the provided arguments could not be found."
                )

        object_list = getattr(self.instance, self.attribute)
        pk_field = getattr(self._meta, 'id_field', None)

        if pk_field is None:
            object_list.pop(obj.pk)
        else:
            object_list.pop(
                self.find_embedded_document(object_list, pk_field, obj.pk))

        # Make sure to delete FileField files
        for fieldname, field in obj._fields.items():
            if isinstance(field, mongoengine_fields.FileField):
                obj[fieldname].delete()

        self.instance.save()
Beispiel #2
0
    def obj_update(self, bundle, skip_errors=False, **kwargs):
        try:
            if not bundle.obj or not getattr(bundle.obj, 'pk', None):
                try:
                    bundle.obj = self.obj_get(bundle=bundle, **kwargs)
                except (queryset.DoesNotExist, exceptions.ObjectDoesNotExist):
                    raise tastypie_exceptions.NotFound(
                        "A document instance matching the provided arguments could not be found."
                    )

            bundle = self.full_hydrate(bundle)

            object_list = getattr(self.instance, self.attribute)
            pk_field = getattr(self._meta, 'id_field', None)

            if pk_field is None:
                object_list[bundle.obj.pk] = bundle.obj
            else:
                object_list[self.find_embedded_document(
                    object_list, pk_field, bundle.obj.pk)] = bundle.obj

            self.save_related(bundle)

            self.instance.save()

            m2m_bundle = self.hydrate_m2m(bundle)
            self.save_m2m(m2m_bundle)
            return bundle
        except mongoengine.ValidationError as ex:
            raise exceptions.ValidationError(ex.message)
    def full_hydrate(self, bundle):
        # When updating objects, we want to force only updates of the same type, and object
        # should be completely replaced if type is changed, so we throw and exception here
        # to direct program logic flow (it is cached and replace instead of update is tried)
        if bundle.obj and self._meta.object_class is not bundle.obj.__class__:
            raise tastypie_exceptions.NotFound(
                "A document instance matching the provided arguments could not be found."
            )

        bundle = super(MongoEngineResource, self).full_hydrate(bundle)

        # We redo check for required fields as Tastypie is not
        # reliable as it does checks in an inconsistent way
        # (https://github.com/toastdriven/django-tastypie/issues/491)
        for field_object in self.fields.itervalues():
            if field_object.readonly or getattr(field_object, '_primary_key',
                                                False):
                continue

            if not field_object.attribute:
                continue

            # Tastypie also skips setting value if it is None, but this means
            # updates to None are ignored: this is not good as it hides invalid
            # PUT/PATCH REST requests (setting value to None which should fail
            # validation (field required) is simply ignored and value is left
            # as it is)
            # (https://github.com/toastdriven/django-tastypie/issues/492)
            # We hydrate field again only if existing value is not None
            if getattr(bundle.obj, field_object.attribute, None) is not None:
                value = NOT_HYDRATED

                # Tastypie also ignores missing fields in PUT,
                # so we check for missing field here
                # (https://github.com/toastdriven/django-tastypie/issues/496)
                if field_object.instance_name not in bundle.data:
                    if field_object.has_default():
                        if callable(field_object.default):
                            value = field_object.default()
                        else:
                            value = field_object.default
                    else:
                        value = None
                else:
                    value = field_object.hydrate(bundle)
                if value is None:
                    setattr(bundle.obj, field_object.attribute, None)

            if field_object.blank or field_object.null:
                continue

            # We are just trying to fix Tastypie here, for other "null" values
            # like [] and {} we leave to MongoEngine validate to catch them
            if getattr(bundle.obj, field_object.attribute, None) is None:
                raise tastypie_exceptions.ApiFieldError(
                    "The '%s' field has no data and doesn't allow a default or null value."
                    % field_object.instance_name)

        return bundle
Beispiel #4
0
 def obj_delete(self, bundle, store, **kwargs):
     with git_checkpoint(store, "Completing Task"):
         try:
             store.log_message("Task %s completed.", kwargs['pk'])
             store.client.task_done(uuid=kwargs['pk'])
             return bundle
         except ValueError:
             raise exceptions.NotFound()
Beispiel #5
0
    def obj_delete(self, bundle, **kwargs):
        self._reset_collection()

        # MongoEngine exceptions are separate from Django exceptions and Tastypie
        # expects Django exceptions, so we catch it here ourselves and raise NotFound
        try:
            return super(MongoEngineResource, self).obj_delete(bundle, **kwargs)
        except queryset.DoesNotExist:
            raise tastypie_exceptions.NotFound("A document instance matching the provided arguments could not be found.")
Beispiel #6
0
 def stop_task(self, request, uuid, store, **kwargs):
     if not request.method == 'POST':
         return HttpResponseNotAllowed(request.method)
     try:
         store.client.task_stop(uuid=uuid)
     except ValueError:
         raise exceptions.NotFound()
     store.log_message("Task %s stopped.", uuid)
     return HttpResponse(
         status=200
     )
Beispiel #7
0
    def obj_update(self, bundle, skip_errors=False, **kwargs):
        self._reset_collection()

        if not bundle.obj or not getattr(bundle.obj, 'pk', None):
            try:
                bundle.obj = self.obj_get(bundle=bundle, **kwargs)
            except (queryset.DoesNotExist, exceptions.ObjectDoesNotExist):
                raise tastypie_exceptions.NotFound("A document instance matching the provided arguments could not be found.")

        self.authorized_update_detail(self.get_object_list(bundle.request), bundle)
        bundle = self.full_hydrate(bundle)
        return self.save(bundle, skip_errors=skip_errors)
Beispiel #8
0
 def stop_task(self, request, uuid, store, **kwargs):
     if not request.method == 'POST':
         return HttpResponseNotAllowed(request.method)
     try:
         store.client.task_stop(uuid=uuid)
     except ValueError:
         raise exceptions.NotFound()
     store.log_message("Task %s stopped.", uuid)
     return HttpResponse(
         json.dumps({
             'message': 'OK',
         }),
         content_type='application/json',
     )
Beispiel #9
0
 def obj_get(self, bundle, store, **kwargs):
     task = store.client.get_task(uuid=kwargs['pk'])[1]
     if not task:
         repository_head = store.repository.head()
         logger.warning(
             'Unable to find task with ID %s in repository %s at %s',
             kwargs['pk'],
             store.local_path,
             repository_head,
             extra={
                 'data': {
                     'store': store,
                     'local_path': store.local_path,
                     'pk': kwargs['pk'],
                     'head': repository_head
                 }
             })
         raise exceptions.NotFound()
     return Task(task, store=store)
    def obj_update(self, bundle, request=None, **kwargs):
        self._reset_collection()

        if not bundle.obj or not getattr(bundle.obj, 'pk', None):
            try:
                bundle.obj = self.obj_get(request, **kwargs)
            except (queryset.DoesNotExist, exceptions.ObjectDoesNotExist):
                raise tastypie_exceptions.NotFound(
                    "A document instance matching the provided arguments could not be found."
                )

        bundle = self.full_hydrate(bundle)

        self.save_related(bundle)

        bundle.obj.save()

        m2m_bundle = self.hydrate_m2m(bundle)
        self.save_m2m(m2m_bundle)
        return bundle
Beispiel #11
0
    def obj_get(self, bundle, **kwargs):
        try:
            stream = datastream.Stream(datastream.get_tags(kwargs['pk']))
        except datastream_exceptions.StreamNotFound:
            raise exceptions.NotFound("Stream '%s' not found." % kwargs['pk'])

        params = self._get_query_params(bundle.request, stream)

        stream.datapoints = datastream.get_data(
            stream_id=stream.id,
            granularity=params['granularity'],
            start=params['start'],
            end=params['end'],
            start_exclusive=params['start_exclusive'],
            end_exclusive=params['end_exclusive'],
            reverse=params['reverse'],
            value_downsamplers=params['value_downsamplers'],
            time_downsamplers=params['time_downsamplers'],
        )

        return stream
Beispiel #12
0
    def obj_update(self, bundle, store, **kwargs):
        with git_checkpoint(store, "Updating Task", sync=True):
            if bundle.data['uuid'] != kwargs['pk']:
                raise exceptions.BadRequest(
                    "Changing the UUID of an existing task is not possible.")
            elif not bundle.data['description']:
                raise exceptions.BadRequest(
                    "You must specify a description for each task.")
            original = store.client.get_task(uuid=kwargs['pk'])[1]
            if not original:
                raise exceptions.NotFound()

            bundle.obj = self.get_empty_task(bundle.request)

            bundle = self.full_hydrate(bundle)

            data = bundle.obj.get_json()
            for k in json.loads(bundle.request.body).keys():
                v = data.get(k)
                if ((k in original.FIELDS and original.FIELDS[k].read_only)
                        or k in self.SYNTHETIC_FIELDS):
                    continue
                original[k] = v

            changes = original.get_changes(keep=True)

            store.client.task_update(original)
            store.log_message(
                "Task %s updated: %s.",
                kwargs['pk'],
                changes,
            )
            bundle.obj = Task(
                store.client.get_task(uuid=kwargs['pk'])[1],
                store=store,
            )
            return bundle
Beispiel #13
0
 def obj_get(self, bundle, store, **kwargs):
     try:
         return Task(store.client.get_task(uuid=kwargs['pk'])[1])
     except ValueError:
         raise exceptions.NotFound()
    def full_hydrate(self, bundle):
        # When updating objects, we want to force only updates of the same type, and object
        # should be completely replaced if type is changed, so we throw and exception here
        # to direct program logic flow (it is cached and replace instead of update is tried)
        if bundle.obj and self._meta.object_class is not bundle.obj.__class__:
            raise tastypie_exceptions.NotFound(
                "A document instance matching the provided arguments could not be found."
            )

        bundle = super(MongoEngineResource, self).full_hydrate(bundle)

        # We redo check for required fields as Tastypie is not
        # reliable as it does checks in an inconsistent way
        # (https://github.com/toastdriven/django-tastypie/issues/491)
        for field_object in self.fields.itervalues():
            if field_object.readonly:
                continue

            if not field_object.attribute:
                continue

            value = NOT_HYDRATED

            # Tastypie also skips setting value if it is None, but this means
            # updates to None are ignored: this is not good as it hides invalid
            # PUT/PATCH REST requests (setting value to None which should fail
            # validation (field required) is simply ignored and value is left
            # as it is)
            # (https://github.com/toastdriven/django-tastypie/issues/492)
            # We hydrate field again only if existing value is not None
            if getattr(bundle.obj, field_object.attribute, None) is not None:
                # Tastypie also ignores missing fields in PUT,
                # so we check for missing field here
                # (https://github.com/toastdriven/django-tastypie/issues/496)
                if field_object.instance_name not in bundle.data:
                    if field_object._default is not tastypie_fields.NOT_PROVIDED:
                        if callable(field_object.default):
                            value = field_object.default()
                        else:
                            value = field_object.default
                    else:
                        value = None
                else:
                    value = field_object.hydrate(bundle)
                if value is None:
                    # This does not really set None in a way that calling
                    # getattr on bundle.obj would return None later on
                    # This is how MongoEngine is implemented
                    # (https://github.com/hmarr/mongoengine/issues/505)
                    setattr(bundle.obj, field_object.attribute, None)

            if field_object.blank or field_object.null:
                continue

            # We are just trying to fix Tastypie here, for other "null" values
            # like [] and {} we leave to validate bellow to catch them
            if getattr(
                    bundle.obj, field_object.attribute, None
            ) is None or value is None:  # We also have to check value, read comment above
                raise tastypie_exceptions.ApiFieldError(
                    "The '%s' field has no data and doesn't allow a default or null value."
                    % field_object.instance_name)

        # We validate MongoEngine object here so that possible exception
        # is thrown before going to MongoEngine layer, wrapped in
        # Django exception so that it is handled properly
        # is_valid method is too early as bundle.obj is not yet ready then
        try:
            # Validation fails for unsaved related resources, so
            # we fake pk here temporary, for validation code to
            # assume resource is saved
            pk = getattr(bundle.obj, 'pk', None)
            try:
                if pk is None:
                    bundle.obj.pk = bson.ObjectId()
                bundle.obj.validate()
            finally:
                if pk is None:
                    bundle.obj.pk = pk
        except mongoengine.ValidationError, e:
            raise exceptions.ValidationError(e.message)