diff --git a/.gitignore b/.gitignore index 1eb011e..1174eae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,11 @@ *.pyc *.pyo *.egg-info +*.code-workspace .idea dist build/ doc/_build/ venv/ +.vscode/ +debug.py diff --git a/odata/navproperty.py b/odata/navproperty.py index 4c5527c..7828e95 100644 --- a/odata/navproperty.py +++ b/odata/navproperty.py @@ -55,12 +55,25 @@ def __init__(self, name, entitycls, collection=False, foreign_key=None): def __repr__(self): return u''.format(self.entitycls) - def instances_from_data(self, raw_data): + def instances_from_data(self, raw_data, connection): if self.is_collection: - return [self.entitycls.__new__(self.entitycls, from_data=d) for d in raw_data] + return [self.instance_from_data(d, connection) for d in raw_data['value']] if raw_data['value'] else [] else: - return self.entitycls.__new__(self.entitycls, from_data=raw_data) - + return self.instance_from_data(raw_data, connection) if raw_data else None + + def instance_from_data(self, raw_data, connection): # mwa: this needs to be seperated form navproperty + entitycls = self._getClass_by_response_type(self.entitycls, raw_data.get('@odata.type')) + e = entitycls.__new__(entitycls, from_data=raw_data) + es = e.__odata__ + es.connection = connection + return e + + def _getClass_by_response_type(self, matched_class, odata_type): + if not odata_type: return matched_class + for subclass in matched_class.__subclasses__(): + if subclass.__odata_type__ == odata_type[1:]: return self._getClass_by_response_type(subclass, odata_type) + return matched_class + def _get_parent_cache(self, instance): es = instance.__odata__ ic = es.nav_cache @@ -102,20 +115,11 @@ def __get__(self, instance, owner): parent_url += '/' url = urljoin(parent_url, self.name) - - if self.is_collection: - if 'collection' not in cache: - raw_data = connection.execute_get(url) - if raw_data: - cache['collection'] = self.instances_from_data(raw_data['value']) - else: - cache['collection'] = [] - return cache['collection'] - else: - if 'single' not in cache: - raw_data = connection.execute_get(url) - if raw_data: - cache['single'] = self.instances_from_data(raw_data) - else: - cache['single'] = None - return cache['single'] + cache_type = 'collection' if self.is_collection else 'single' + + try: + return cache[cache_type] + except KeyError: + raw_data = connection.execute_get(url) + cache[cache_type] = self.instances_from_data(raw_data, connection) + return cache[cache_type] \ No newline at end of file diff --git a/odata/query.py b/odata/query.py index 4d276ad..5d54972 100644 --- a/odata/query.py +++ b/odata/query.py @@ -73,7 +73,7 @@ def __iter__(self): for row in value: yield self._create_model(row) - if '@odata.nextLink' in data: + if '@odata.nextLink' in data and not '$top' in options.keys(): #do not load next page on userpaging url = urljoin(self.entity.__odata_url_base__, data['@odata.nextLink']) options = {} # we get all options in the nextLink url else: