Add chained method call API for QueryChain
This commit is contained in:
@@ -55,10 +55,18 @@ database.
|
|||||||
list(chain) # all blog posts but not articles and news items
|
list(chain) # all blog posts but not articles and news items
|
||||||
|
|
||||||
|
|
||||||
chain.offset = 4
|
chain = chain.offset(4)
|
||||||
list(chain) # last blog post, and first four articles
|
list(chain) # last blog post, and first four articles
|
||||||
|
|
||||||
|
|
||||||
|
Just like with original query object the limit and offset can be chained to
|
||||||
|
return a new QueryChain.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
chain = chain.limit(5).offset(7)
|
||||||
|
|
||||||
|
|
||||||
Chain slicing
|
Chain slicing
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
@@ -91,18 +99,18 @@ class QueryChain(object):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, queries, limit=None, offset=None):
|
def __init__(self, queries, limit=None, offset=None):
|
||||||
self.queries = queries
|
self.queries = queries
|
||||||
self.limit = limit
|
self._limit = limit
|
||||||
self.offset = offset
|
self._offset = offset
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
consumed = 0
|
consumed = 0
|
||||||
skipped = 0
|
skipped = 0
|
||||||
for query in self.queries:
|
for query in self.queries:
|
||||||
query_copy = copy(query)
|
query_copy = copy(query)
|
||||||
if self.limit:
|
if self._limit:
|
||||||
query = query.limit(self.limit - consumed)
|
query = query.limit(self._limit - consumed)
|
||||||
if self.offset:
|
if self._offset:
|
||||||
query = query.offset(self.offset - skipped)
|
query = query.offset(self._offset - skipped)
|
||||||
|
|
||||||
obj_count = 0
|
obj_count = 0
|
||||||
for obj in query:
|
for obj in query:
|
||||||
@@ -115,12 +123,18 @@ class QueryChain(object):
|
|||||||
else:
|
else:
|
||||||
skipped += obj_count
|
skipped += obj_count
|
||||||
|
|
||||||
|
def limit(self, value):
|
||||||
|
return self[:value]
|
||||||
|
|
||||||
|
def offset(self, value):
|
||||||
|
return self[value:]
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if isinstance(key, slice):
|
if isinstance(key, slice):
|
||||||
return self.__class__(
|
return self.__class__(
|
||||||
queries=self.queries,
|
queries=self.queries,
|
||||||
limit=key.stop,
|
limit=key.stop if key.stop is not None else self._limit,
|
||||||
offset=key.start
|
offset=key.start if key.start is not None else self._offset
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
for obj in self[key:1]:
|
for obj in self[key:1]:
|
||||||
|
@@ -57,25 +57,24 @@ class TestQueryChain(TestCase):
|
|||||||
assert len(list(self.chain)) == 9
|
assert len(list(self.chain)) == 9
|
||||||
|
|
||||||
def test_iter_with_limit(self):
|
def test_iter_with_limit(self):
|
||||||
self.chain.limit = 4
|
chain = self.chain.limit(4)
|
||||||
objects = list(self.chain)
|
objects = list(chain)
|
||||||
assert self.users == objects[0:2]
|
assert self.users == objects[0:2]
|
||||||
assert self.articles[0:2] == objects[2:]
|
assert self.articles[0:2] == objects[2:]
|
||||||
|
|
||||||
def test_iter_with_offset(self):
|
def test_iter_with_offset(self):
|
||||||
self.chain.offset = 3
|
chain = self.chain.offset(3)
|
||||||
objects = list(self.chain)
|
objects = list(chain)
|
||||||
assert self.articles[1:] + self.posts == objects
|
assert self.articles[1:] + self.posts == objects
|
||||||
|
|
||||||
def test_iter_with_limit_and_offset(self):
|
def test_iter_with_limit_and_offset(self):
|
||||||
self.chain.offset = 3
|
chain = self.chain.offset(3).limit(4)
|
||||||
self.chain.limit = 4
|
objects = list(chain)
|
||||||
objects = list(self.chain)
|
|
||||||
assert self.articles[1:] + self.posts[0:1] == objects
|
assert self.articles[1:] + self.posts[0:1] == objects
|
||||||
|
|
||||||
def test_iter_with_offset_spanning_multiple_queries(self):
|
def test_iter_with_offset_spanning_multiple_queries(self):
|
||||||
self.chain.offset = 7
|
chain = self.chain.offset(7)
|
||||||
objects = list(self.chain)
|
objects = list(chain)
|
||||||
assert self.posts[1:] == objects
|
assert self.posts[1:] == objects
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
@@ -83,8 +82,8 @@ class TestQueryChain(TestCase):
|
|||||||
|
|
||||||
def test_getitem_with_slice(self):
|
def test_getitem_with_slice(self):
|
||||||
chain = self.chain[1:]
|
chain = self.chain[1:]
|
||||||
assert chain.offset == 1
|
assert chain._offset == 1
|
||||||
assert chain.limit is None
|
assert chain._limit is None
|
||||||
|
|
||||||
def test_getitem_with_single_key(self):
|
def test_getitem_with_single_key(self):
|
||||||
article = self.chain[2]
|
article = self.chain[2]
|
||||||
|
Reference in New Issue
Block a user