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)
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)
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
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)
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)
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
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)
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)
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 []