Ejemplo n.º 1
0
    def _get_from_id_or_pk(self, id=None, pk=None, **kwargs):
        """
        Returns an object given an id or pk, request directly with the
        get_resource_url_detail method without filtering on ids
        (as Django's ORM do).
        """
        clone = self._clone()

        # Instantiation of clone.model is necessary because we can't set
        # a staticmethod for get_resource_url_detail and avoid to set it
        # for all model without relying on get_resource_url_list
        instance = clone.model()
        if pk is None:
            instance.id = id
        else:
            instance.pk = pk
        try:
            parameters = clone.query.parameters
            logger.debug(
                """Retrieving : "%s" through %s with parameters "%s" """ %
                (clone.model.__name__, instance.get_resource_url_detail(),
                 force_text(parameters)))
            if ROA_SSL_CA:
                response = self._get_requests_client().get(
                    instance.get_resource_url_detail(),
                    params=parameters,
                    headers=self._get_http_headers(),
                    verify=ROA_SSL_CA)
            else:
                response = self._get_requests_client().get(
                    instance.get_resource_url_detail(),
                    params=parameters,
                    headers=self._get_http_headers())
        except Exception as e:
            raise ROAException(e)

        response = response.text.encode("utf-8")

        for local_name, remote_name in ROA_MODEL_NAME_MAPPING:
            response = response.replace(remote_name, local_name)

        # Deserializing objects:
        data = self.model.get_parser().parse(BytesIO(response))
        serializer = self.model.get_serializer(data=data)
        for field in serializer.fields.items():
            validators = field[1].validators
            field[1].validators = []
            for validator in validators:
                if validator.__class__.__name__ != "UniqueValidator":
                    field[1].validators.append(validator)

        if not serializer.is_valid():
            raise ROAException('Invalid deserialization for %s model: %s' %
                               (self.model, serializer.errors))

        return serializer.Meta.model(**serializer.validated_data)
Ejemplo n.º 2
0
    def iterator(self):
        """
        An iterator over the results from applying this QuerySet to the
        remote web service.
        """
        resource = Resource(self.model.get_resource_url_list(),
                            filters=ROA_FILTERS,
                            **ROA_SSL_ARGS)
        try:
            parameters = self.query.parameters
            logger.debug(
                u"""Requesting: "%s" through %s with parameters "%s" """ %
                (self.model.__name__, resource.uri, force_unicode(parameters)))
            response = resource.get(headers=self._get_http_headers(),
                                    **parameters)
        except ResourceNotFound:
            return
        except Exception as e:
            raise ROAException(e)

        response = force_unicode(
            response.body_string()).encode(DEFAULT_CHARSET)

        # Deserializing objects:
        data = self.model.get_parser().parse(StringIO(response))

        # Check limit_start and limit_stop arguments for pagination and only
        # slice data if they are both numeric and there are results left to go.
        # We only perform this check on lists.
        limit_start = getattr(self.query, 'limit_start', None)
        limit_stop = getattr(self.query, 'limit_stop', None)
        if (isinstance(limit_start, int) and isinstance(limit_stop, int)
                and limit_stop - limit_start < len(data)
                and limit_stop <= len(data) and isinstance(data, list)):
            data = data[limit_start:limit_stop]

        # [] is the case of empty no-paginated result
        if data != []:
            serializer = self.model.get_serializer(data=data)
            if not serializer.is_valid():
                raise ROAException(
                    u'Invalid deserialization for %s model: %s' %
                    (self.model, serializer.errors))

            i = 0
            for obj in serializer.validated_data:
                obj['id'] = serializer.initial_data[i].get('id', None)

                i += 1
                yield self.model(**obj)
Ejemplo n.º 3
0
    def _get_from_id_or_pk(self, id=None, pk=None, **kwargs):
        """
        Returns an object given an id or pk, request directly with the
        get_resource_url_detail method without filtering on ids
        (as Django's ORM do).
        """
        clone = self._clone()

        # Instantiation of clone.model is necessary because we can't set
        # a staticmethod for get_resource_url_detail and avoid to set it
        # for all model without relying on get_resource_url_list
        instance = clone.model()
        if pk is None:
            instance.id = id
        else:
            instance.pk = pk
        extra_args = {}
        extra_args.update(kwargs)
        extra_args.update(ROA_SSL_ARGS)
        resource = Resource(instance.get_resource_url_detail(),
                            filters=ROA_FILTERS,
                            **extra_args)
        try:
            parameters = clone.query.parameters
            logger.debug(
                u"""Retrieving : "%s" through %s with parameters "%s" """ %
                (clone.model.__name__, resource.uri,
                 force_unicode(parameters)))
            response = resource.get(headers=self._get_http_headers(),
                                    **parameters)
        except Exception as e:
            raise ROAException(e)

        response = force_unicode(
            response.body_string()).encode(DEFAULT_CHARSET)

        for local_name, remote_name in ROA_MODEL_NAME_MAPPING:
            response = response.replace(remote_name, local_name)

        # Deserializing objects:
        data = self.model.get_parser().parse(StringIO(response))
        serializer = self.model.get_serializer(data=data)
        if not serializer.is_valid():
            raise ROAException(
                u'Invalid deserialization for {} model: {}'.format(
                    self.model, serializer.errors))

        return serializer.object
Ejemplo n.º 4
0
    def count(self):
        """
        Returns the number of records as an integer.

        The result is not cached nor comes from cache, cache must be handled
        by the server.
        """
        clone = self._clone()

        # Instantiation of clone.model is necessary because we can't set
        # a staticmethod for get_resource_url_count and avoid to set it
        # for all model without relying on get_resource_url_list
        instance = clone.model()
        resource = Resource(instance.get_resource_url_count(),
                            filters=ROA_FILTERS,
                            **ROA_SSL_ARGS)
        try:
            parameters = clone.query.parameters
            logger.debug(
                u"""Counting  : "%s" through %s with parameters "%s" """ %
                (clone.model.__name__, resource.uri,
                 force_unicode(parameters)))
            response = resource.get(headers=self._get_http_headers(),
                                    **parameters)
        except Exception as e:
            raise ROAException(e)

        response = force_unicode(
            response.body_string()).encode(DEFAULT_CHARSET)
        data = self.model.get_parser().parse(StringIO(response))
        return self.model.count_response(data)
Ejemplo n.º 5
0
    def complex_filter(self, filter_obj):
        """
        Returns a new QuerySet instance with filter_obj added to the filters.

        filter_obj can be a Q object (or anything with an add_to_query()
        method) or a dictionary of keyword lookup arguments.

        This exists to support framework features such as 'limit_choices_to',
        and usually it will be more natural to use other methods.
        """
        if isinstance(filter_obj, Q) or hasattr(filter_obj, 'add_to_query'):
            raise ROAException('Not implemented yet')
        return self.filter(**filter_obj)
Ejemplo n.º 6
0
    def iterator(self):
        """
        An iterator over the results from applying this QuerySet to the
        remote web service.
        """
        resource = Resource(
            self.model.get_resource_url_list(**self.query.filters),
            filters=ROA_FILTERS,
            **ROA_SSL_ARGS)
        try:
            parameters = self.query.parameters
            logger.debug(
                u"""Requesting: "%s" through %s with parameters "%s" """ %
                (self.model.__name__, resource.uri, force_unicode(parameters)))
            response = resource.get(headers=self._get_http_headers(),
                                    **parameters)
        except ResourceNotFound:
            return
        except Exception as e:
            raise ROAException(e)

        response = force_unicode(
            response.body_string()).encode(DEFAULT_CHARSET)

        # Deserializing objects:
        data = self.model.get_parser().parse(StringIO(response))

        # [] is the case of empty no-paginated result
        if data != []:
            serializer = self.model.get_serializer(data=data)
            if not serializer.is_valid():
                raise ROAException(
                    u'Invalid deserialization for {} model: {}'.format(
                        self.model, serializer.errors))

            for obj in serializer.object:
                yield obj
Ejemplo n.º 7
0
    def count(self):
        """
        Returns the number of records as an integer.

        The result is not cached nor comes from cache, cache must be handled
        by the server.
        """
        clone = self._clone()

        # Instantiation of clone.model is necessary because we can't set
        # a staticmethod for get_resource_url_count and avoid to set it
        # for all model without relying on get_resource_url_list
        instance = clone.model()

        try:
            parameters = clone.query.parameters
            logger.debug(
                """Retrieving : "%s" through %s with parameters "%s" """ %
                (clone.model.__name__, self.model.get_resource_url_list(),
                 force_text(parameters)))
            if ROA_SSL_CA:
                response = self._get_requests_client().get(
                    self.model.get_resource_url_list(),
                    params=parameters,
                    headers=self._get_http_headers(),
                    verify=ROA_SSL_CA)
            else:
                response = self._get_requests_client().get(
                    self.model.get_resource_url_list(),
                    params=parameters,
                    headers=self._get_http_headers())
        except Exception as e:
            raise ROAException(e)

        response = response.text.encode("utf-8")

        data = self.model.get_parser().parse(BytesIO(response))
        return self.model.count_response(data)
Ejemplo n.º 8
0
    def save_base(self,
                  raw=False,
                  cls=None,
                  origin=None,
                  force_insert=False,
                  force_update=False,
                  using=None,
                  update_fields=None):
        """
        Does the heavy-lifting involved in saving. Subclasses shouldn't need to
        override this method. It's separate from save() in order to hide the
        need for overrides of save() to pass around internal-only parameters
        ('raw', 'cls', and 'origin').
        """

        assert not (force_insert and force_update)

        record_exists = False

        if cls is None:
            cls = self.__class__
            meta = cls._meta
            if not meta.proxy:
                origin = cls
        else:
            meta = cls._meta

        if origin and not getattr(meta, "auto_created", False):
            signals.pre_save.send(sender=origin, instance=self, raw=raw)

        model_name = str(meta)

        # If we are in a raw save, save the object exactly as presented.
        # That means that we don't try to be smart about saving attributes
        # that might have come from the parent class - we just save the
        # attributes we have been given to the class we have been given.
        # We also go through this process to defer the save of proxy objects
        # to their actual underlying model.
        if not raw or meta.proxy:
            if meta.proxy:
                org = cls
            else:
                org = None
            for parent, field in meta.parents.items():
                # At this point, parent's primary key field may be unknown
                # (for example, from administration form which doesn't fill
                # this field). If so, fill it.
                if field and getattr(
                        self, parent._meta.pk.attname) is None and getattr(
                            self, field.attname) is not None:
                    setattr(self, parent._meta.pk.attname,
                            getattr(self, field.attname))

                self.save_base(cls=parent, origin=org, using=using)

                if field:
                    setattr(self, field.attname,
                            self._get_pk_val(parent._meta))
            if meta.proxy:
                return

        if not meta.proxy:
            pk_val = self._get_pk_val(meta)
            pk_is_set = pk_val is not None

            get_args = {}
            get_args[ROA_ARGS_NAMES_MAPPING.get('FORMAT',
                                                'format')] = ROA_FORMAT
            get_args.update(ROA_CUSTOM_ARGS)

            # Construct Json payload
            serializer = self.get_serializer(self)
            payload = self.get_renderer().render(serializer.data)

            # Add serializer content_type
            headers = get_roa_headers()
            headers.update(self.get_serializer_content_type())

            # check if resource use custom primary key
            if not meta.pk.attname in ['pk', 'id']:
                # consider it might be inserting so check it first
                # @todo: try to improve this block to check if custom pripary key is not None first
                resource = Resource(self.get_resource_url_detail(),
                                    filters=ROA_FILTERS,
                                    **ROA_SSL_ARGS)
                try:
                    response = resource.get(payload=None,
                                            headers=headers,
                                            **get_args)
                except ResourceNotFound:
                    # since such resource does not exist, it's actually creating
                    pk_is_set = False
                except RequestFailed:
                    pk_is_set = False

            if force_update or pk_is_set and not self.pk is None:
                record_exists = True
                resource = Resource(self.get_resource_url_detail(),
                                    filters=ROA_FILTERS,
                                    **ROA_SSL_ARGS)
                try:
                    logger.debug(
                        u"""Modifying : "%s" through %s with payload "%s" and GET args "%s" """
                        % (force_unicode(self), force_unicode(resource.uri),
                           force_unicode(payload), force_unicode(get_args)))
                    response = resource.put(payload=payload,
                                            headers=headers,
                                            **get_args)
                except RequestFailed as e:
                    raise ROAException(e)
            else:
                record_exists = False
                resource = Resource(self.get_resource_url_list(),
                                    filters=ROA_FILTERS,
                                    **ROA_SSL_ARGS)
                try:
                    logger.debug(
                        u"""Creating  : "%s" through %s with payload "%s" and GET args "%s" """
                        % (force_unicode(self), force_unicode(resource.uri),
                           force_unicode(payload), force_unicode(get_args)))
                    response = resource.post(payload=payload,
                                             headers=headers,
                                             **get_args)
                except RequestFailed as e:
                    raise ROAException(e)

            response = force_unicode(
                response.body_string()).encode(DEFAULT_CHARSET)

            data = self.get_parser().parse(StringIO(response))
            serializer = self.get_serializer(data=data)
            if not serializer.is_valid():
                raise ROAException(
                    u'Invalid deserialization for %s model: %s' %
                    (self, serializer.errors))

            obj = self.__class__(**serializer.initial_data)
            try:
                self.pk = int(obj.pk)
            except ValueError:
                self.pk = obj.pk
            self = obj

        if origin:
            signals.post_save.send(sender=origin,
                                   instance=self,
                                   created=(not record_exists),
                                   raw=raw)
Ejemplo n.º 9
0
    def iterator(self):
        """
        An iterator over the results from applying this QuerySet to the
        remote web service.
        """

        try:
            parameters = self.query.parameters
            logger.debug(
                """Retrieving : "%s" through %s with parameters "%s" """ %
                (self.model.__name__, self.model.get_resource_url_list(),
                 force_text(parameters)))
            if ROA_SSL_CA:
                response = self._get_requests_client().get(
                    self.model.get_resource_url_list(),
                    params=parameters,
                    headers=self._get_http_headers(),
                    verify=ROA_SSL_CA)
            else:
                response = self._get_requests_client().get(
                    self.model.get_resource_url_list(),
                    params=parameters,
                    headers=self._get_http_headers())
        except Exception as e:
            raise ROAException(e)

        # Deserializing objects:
        response = response.text.encode("utf-8")
        data = self.model.get_parser().parse(BytesIO(response))

        # Check limit_start and limit_stop arguments for pagination and only
        # slice data if they are both numeric and there are results left to go.
        # We only perform this check on lists.
        limit_start = getattr(self.query, 'limit_start', None)
        limit_stop = getattr(self.query, 'limit_stop', None)
        if (isinstance(limit_start, int) and isinstance(limit_stop, int)
                and limit_stop - limit_start < len(data)
                and limit_stop <= len(data) and isinstance(data, list)):
            data = data[limit_start:limit_stop]

        # [] is the case of empty no-paginated result
        if data != []:
            result = []

            serializer = self.model.get_serializer(data=data)
            for field in serializer.child.fields.items():
                validators = field[1].validators
                field[1].validators = []
                for validator in validators:
                    if validator.__class__.__name__ != "UniqueValidator":
                        field[1].validators.append(validator)

            if not serializer.is_valid():
                raise ROAException('Invalid deserialization for %s model: %s' %
                                   (self.model, serializer.errors))

            for item in serializer.validated_data:
                obj = serializer.child.Meta.model(**item)
                result.append(obj)

            return result

        return []