def execute_update(self, query): table = query.model._meta.db_table # this will break in multi-row updates assert (len(query.where.children) == 1 and query.where.children[0].lookup_name in ('exact', 'in') and query.where.children[0].lhs.target.column == 'Id') pk = query.where.children[0].rhs assert pk headers = {'Content-Type': 'application/json'} post_data = extract_values(query) log.debug('UPDATE %s(%s)%s' % (table, pk, post_data)) if isinstance(pk, (tuple, list, SalesforceQuerySet)): if not self.use_soap_for_bulk: # bulk by REST url = rest_api_url(self.session, 'composite/batch') last_mod = None if pk and hasattr(pk[0], 'pk'): last_mod = max(getattr(x, fld.name) for x in pk if hasattr(x, 'pk') for fld in x._meta.fields if fld.db_column=='LastModifiedDate' ) if last_mod is None: last_mod = datetime.datetime.utcnow() post_data = { 'batchRequests': [{'method' : 'PATCH', 'url' : 'v{0}/sobjects/{1}/{2}'.format(salesforce.API_VERSION, table, getattr(x, 'pk', x)), 'richInput': post_data } for x in pk ] } import time headers.update({'If-Unmodified-Since': time.strftime('%a, %d %b %Y %H:%M:%S GMT', (last_mod + datetime.timedelta(seconds=0)).timetuple())}) _ret = handle_api_exceptions(url, self.session.post, headers=headers, data=json.dumps(post_data), _cursor=self) else: # bulk by SOAP svc = salesforce.utils.get_soap_client('salesforce') out = [] for x in pk: d = post_data.copy() d.update({'type': table, 'Id': getattr(x, 'pk', x)}) out.append(d) ret = svc.update(out) return ret else: # single request url = rest_api_url(self.session, 'sobjects', table, pk) _ret = handle_api_exceptions(url, self.session.patch, headers=headers, data=json.dumps(post_data), _cursor=self) self.rowcount = 1 return _ret
def execute_insert(self, query): table = query.model._meta.db_table headers = {'Content-Type': 'application/json'} post_data = extract_values(query) if len(post_data) == 1: # single object url = rest_api_url(self.session, 'sobjects', table, '') post_data = post_data[0] elif not self.use_soap_for_bulk: # bulk by REST url = rest_api_url(self.session, 'composite/batch') post_data = { 'batchRequests': [{ 'method': 'POST', 'url': 'v{0}/sobjects/{1}'.format(salesforce.API_VERSION, table), 'richInput': row } for row in post_data] } else: # bulk by SOAP svc = salesforce.utils.get_soap_client('salesforce') for x in post_data: x.update({'type': table}) ret = svc.create(post_data) return ret log.debug('INSERT %s%s' % (table, post_data)) return handle_api_exceptions(url, self.session.post, headers=headers, data=json.dumps(post_data), _cursor=self)
def execute_insert(self, query): table = query.model._meta.db_table headers = {'Content-Type': 'application/json'} post_data = extract_values(query) if len(post_data) == 1: # single object url = rest_api_url(self.session, 'sobjects', table, '') post_data = post_data[0] elif not self.use_soap_for_bulk: # bulk by REST url = rest_api_url(self.session, 'composite/batch') post_data = { 'batchRequests': [{'method': 'POST', 'url': 'v{0}/sobjects/{1}'.format(salesforce.API_VERSION, table), 'richInput': row } for row in post_data ] } else: # bulk by SOAP svc = salesforce.utils.get_soap_client('salesforce') for x in post_data: x.update({'type': table}) ret = svc.create(post_data) return ret log.debug('INSERT %s%s' % (table, post_data)) return handle_api_exceptions(url, self.session.post, headers=headers, data=json.dumps(post_data), _cursor=self)
def saveAtt(idProv, nameProv): ''' Funcion para insertar los Attachments con su respectivo Provision relacionada. ''' # Hacemos conexion con Saleforce por medio de session, y consultar el contenido de cada archivo adjunto session = connections['salesforce'].sf_session attch = Attachment.objects.filter(parent=idProv) for a in attch: url = session.auth.instance_url + a.body blob2 = handle_api_exceptions(url, session.get)._content file = SimpleUploadedFile(a.name, blob2) try: #Si ya existe el archivo adjunto, no volveremos a cargarlo adj = Att.objects.filter(provision=str(nameProv), name=a.name) if not (adj.count()): print("===================> Create Attachment of " + nameProv + " <================") print("Atta => " + a.name) Att.objects.create(name=a.name, index=file, provision_id=str(nameProv)) #else: #print("===================> Update Attachment of " + nameProv + " <================") #for a in adj: # a.index = file # a.provision = str(nameP) #print(adj) except: print( '============ Error Save / Update Attachment(s); Provision: ' + nameProv)
def table_list_cache(self): if self._table_list_cache is None: url = query.rest_api_url(self.connection.sf_session, 'sobjects') log.debug('Request API URL: %s' % url) response = driver.handle_api_exceptions(url, self.connection.sf_session.get) # charset is detected from headers by requests package self._table_list_cache = response.json(object_pairs_hook=OrderedDict) return self._table_list_cache
def execute_select(self, q, args): processed_sql = str(q) % process_args(args) service = 'query' if not getattr(self.query, 'is_query_all', False) else 'queryAll' url = rest_api_url(self.session, service, '?' + urlencode(dict(q=processed_sql))) log.debug(processed_sql) return handle_api_exceptions(url, self.session.get, _cursor=self)
def table_list_cache(self): if self._table_list_cache is None: url = query.rest_api_url(self.connection.sf_session, 'sobjects') log.debug('Request API URL: %s' % url) response = driver.handle_api_exceptions( url, self.connection.sf_session.get) # charset is detected from headers by requests package self._table_list_cache = response.json( object_pairs_hook=OrderedDict) return self._table_list_cache
def table_description_cache(self, table): if table not in self._table_description_cache: url = query.rest_api_url(self.connection.sf_session, 'sobjects', table, 'describe/') log.debug('Request API URL: %s' % url) response = driver.handle_api_exceptions(url, self.connection.sf_session.get) self._table_description_cache[table] = response.json(object_pairs_hook=OrderedDict) assert self._table_description_cache[table]['fields'][0]['type'] == 'id' assert self._table_description_cache[table]['fields'][0]['name'] == 'Id' del self._table_description_cache[table]['fields'][0] return self._table_description_cache[table]
def id_request(self): """The Force.com Identity Service (return type dict of text_type)""" # https://developer.salesforce.com/page/Digging_Deeper_into_OAuth_2.0_at_Salesforce.com?language=en&language=en#The_Force.com_Identity_Service if 'id' in self.oauth: url = self.oauth['id'] else: # dynamic auth without 'id' parameter url = self.urls_request()['identity'] ret = handle_api_exceptions(url, self.session.get, _cursor=self) return ret.json()
def urls_request(self): """Empty REST API request is useful after long inactivity before POST. It ensures that the token will remain valid for at least half life time of the new token. Otherwise it would be an awkward doubt if a timeout on a lost connection is possible together with token expire in a post request (insert). """ url = rest_api_url(self.session, '') ret = handle_api_exceptions(url, self.session.get, _cursor=self) return str_dict(ret.json())
def table_description_cache(self, table): if table not in self._table_description_cache: url = query.rest_api_url(self.connection.sf_session, 'sobjects', table, 'describe/') log.debug('Request API URL: %s' % url) response = driver.handle_api_exceptions( url, self.connection.sf_session.get) self._table_description_cache[table] = response.json( object_pairs_hook=OrderedDict) assert self._table_description_cache[table]['fields'][0][ 'type'] == 'id' assert self._table_description_cache[table]['fields'][0][ 'name'] == 'Id' del self._table_description_cache[table]['fields'][0] return self._table_description_cache[table]
def execute_select(self, q, args): processed_sql = str(q) % tuple(arg_to_soql(x) for x in args) service = 'query' if not getattr(self.query, 'is_query_all', False) else 'queryAll' url = rest_api_url(self.session, service, '?' + urlencode(dict(q=processed_sql))) log.debug(processed_sql) if q != MIGRATIONS_QUERY_TO_BE_IGNORED: # normal query return handle_api_exceptions(url, self.session.get, _cursor=self) else: # Nothing queried about django_migrations to SFDC and immediately responded that # nothing about migration status is recorded in SFDC. # # That is required by "makemigrations" in Django 1.10+ to accept this query. # Empty results are possible. # (It could be eventually replaced by: "SELECT app__c, Name FROM django_migrations__c") self.results = iter([]) return
def execute_delete(self, query): table = query.model._meta.db_table ## the root where node's children may itself have children.. def recurse_for_pk(children): for node in children: if hasattr(node, 'rhs'): pk = node.rhs[0] else: try: pk = node[-1][0] except TypeError: pk = recurse_for_pk(node.children) return pk pk = recurse_for_pk(self.query.where.children) assert pk url = rest_api_url(self.session, 'sobjects', table, pk) log.debug('DELETE %s(%s)' % (table, pk)) ret = handle_api_exceptions(url, self.session.delete, _cursor=self) self.rowcount = 1 if (ret and ret.status_code == 204) else 0 return ret
def versions_request(self): """List Available REST API Versions""" url = self.session.auth.instance_url + '/services/data/' ret = handle_api_exceptions(url, self.session.get, _cursor=self) return [str_dict(x) for x in ret.json()]
def execute_update(self, query): table = query.model._meta.db_table # this will break in multi-row updates assert (len(query.where.children) == 1 and query.where.children[0].lookup_name in ('exact', 'in') and query.where.children[0].lhs.target.column == 'Id') pk = query.where.children[0].rhs assert pk headers = {'Content-Type': 'application/json'} post_data = extract_values(query) log.debug('UPDATE %s(%s)%s' % (table, pk, post_data)) if isinstance(pk, (tuple, list, SalesforceQuerySet)): if not self.use_soap_for_bulk: # bulk by REST url = rest_api_url(self.session, 'composite/batch') last_mod = None if pk and hasattr(pk[0], 'pk'): last_mod = max( getattr(x, fld.name) for x in pk if hasattr(x, 'pk') for fld in x._meta.fields if fld.db_column == 'LastModifiedDate') if last_mod is None: last_mod = datetime.datetime.utcnow() post_data = { 'batchRequests': [{ 'method': 'PATCH', 'url': 'v{0}/sobjects/{1}/{2}'.format(salesforce.API_VERSION, table, getattr(x, 'pk', x)), 'richInput': post_data } for x in pk] } import time headers.update({ 'If-Unmodified-Since': time.strftime('%a, %d %b %Y %H:%M:%S GMT', (last_mod + datetime.timedelta(seconds=0)).timetuple()) }) _ret = handle_api_exceptions(url, self.session.post, headers=headers, data=json.dumps(post_data), _cursor=self) else: # bulk by SOAP svc = salesforce.utils.get_soap_client('salesforce') out = [] for x in pk: d = post_data.copy() d.update({'type': table, 'Id': getattr(x, 'pk', x)}) out.append(d) ret = svc.update(out) return ret else: # single request url = rest_api_url(self.session, 'sobjects', table, pk) _ret = handle_api_exceptions(url, self.session.patch, headers=headers, data=json.dumps(post_data), _cursor=self) self.rowcount = 1 return _ret
def query_more(self, nextRecordsUrl): url = u'%s%s' % (self.session.auth.instance_url, nextRecordsUrl) return handle_api_exceptions(url, self.session.get, _cursor=self)