-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #117 from ilex/master
Add projection methods only(), exclude() and other to QuerySet
- Loading branch information
Showing
12 changed files
with
1,353 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
from motorengine.query_builder.transform import transform_field_list_query | ||
|
||
__all__ = ('QueryFieldList',) | ||
|
||
|
||
class QueryFieldList(object): | ||
'''Object that handles combinations of .only() and .exclude() calls''' | ||
ONLY = 1 | ||
EXCLUDE = 0 | ||
|
||
def __init__( | ||
self, fields=None, value=ONLY, always_include=None, _only_called=False | ||
): | ||
''' | ||
The QueryFieldList builder | ||
:param fields: A list of fields used in `.only()` or `.exclude()` | ||
:param value: How to handle the fields; either `ONLY` or `EXCLUDE` | ||
:param always_include: Any fields to always_include eg `_cls` | ||
:param _only_called: Has `.only()` been called? If so its a set of | ||
fields otherwise it performs a union. | ||
''' | ||
self.value = value | ||
self.fields = set(fields or []) | ||
self.always_include = set(always_include or []) | ||
self._id = None | ||
self._only_called = _only_called | ||
self.slice = {} | ||
|
||
def __add__(self, f): | ||
if isinstance(f.value, dict): | ||
for field in f.fields: | ||
self.slice[field] = f.value | ||
if not self.fields: | ||
self.fields = f.fields | ||
elif not self.fields: | ||
self.fields = f.fields | ||
self.value = f.value | ||
self.slice = {} | ||
elif self.value is self.ONLY and f.value is self.ONLY: | ||
self._clean_slice() | ||
if self._only_called: | ||
self.fields = self.fields.union(f.fields) | ||
else: | ||
self.fields = f.fields | ||
elif self.value is self.EXCLUDE and f.value is self.EXCLUDE: | ||
self.fields = self.fields.union(f.fields) | ||
self._clean_slice() | ||
elif self.value is self.ONLY and f.value is self.EXCLUDE: | ||
self.fields -= f.fields | ||
self._clean_slice() | ||
elif self.value is self.EXCLUDE and f.value is self.ONLY: | ||
self.value = self.ONLY | ||
self.fields = f.fields - self.fields | ||
self._clean_slice() | ||
|
||
# _id should be saved separately to avoid situation such as | ||
# exclude('_id').only('other') so the previous code of this method | ||
# remove _id from self.fields (its a normal behavior for any field | ||
# except for _id because _id field cannot be removed with only) | ||
if '_id' in f.fields: | ||
self._id = f.value | ||
|
||
if self.always_include: | ||
if self.value is self.ONLY and self.fields: | ||
if sorted(self.slice.keys()) != sorted(self.fields): | ||
self.fields = self.fields.union(self.always_include) | ||
else: | ||
# if this is exclude - remove from fields values from | ||
# always included fields | ||
self.fields -= self.always_include | ||
|
||
if getattr(f, '_only_called', False): | ||
self._only_called = True | ||
return self | ||
|
||
# python2 | ||
def __nonzero__(self): | ||
return bool(self.fields) | ||
|
||
# python3 | ||
def __bool__(self): | ||
return bool(self.fields) | ||
|
||
def as_dict(self): | ||
field_list = dict((field, self.value) for field in self.fields) | ||
|
||
if self.slice: | ||
field_list.update(self.slice) | ||
|
||
if self._id is not None: | ||
field_list['_id'] = self._id | ||
|
||
return field_list | ||
|
||
def to_query(self, document): | ||
''' Transform to query using db names for fields | ||
:param document - class of the document | ||
''' | ||
return transform_field_list_query(document, self.as_dict()) | ||
|
||
def reset(self): | ||
self.fields = set([]) | ||
self.slice = {} | ||
self.value = self.ONLY | ||
self._id = None | ||
|
||
def _clean_slice(self): | ||
if self.slice: | ||
for field in set(self.slice.keys()) - self.fields: | ||
del self.slice[field] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.