Manipulate how you load this document's fields. Used by `.only()` and `.exclude()` to manipulate which fields to retrieve. If called directly, use a set of kwargs similar to the MongoDB projection document. For example: Include only a subset of fields: p
(self, _only_called=False, **kwargs)
| 1072 | return self.fields(**fields) |
| 1073 | |
| 1074 | def fields(self, _only_called=False, **kwargs): |
| 1075 | """Manipulate how you load this document's fields. Used by `.only()` |
| 1076 | and `.exclude()` to manipulate which fields to retrieve. If called |
| 1077 | directly, use a set of kwargs similar to the MongoDB projection |
| 1078 | document. For example: |
| 1079 | |
| 1080 | Include only a subset of fields: |
| 1081 | |
| 1082 | posts = BlogPost.objects(...).fields(author=1, title=1) |
| 1083 | |
| 1084 | Exclude a specific field: |
| 1085 | |
| 1086 | posts = BlogPost.objects(...).fields(comments=0) |
| 1087 | |
| 1088 | To retrieve a subrange or sublist of array elements, |
| 1089 | support exist for both the `slice` and `elemMatch` projection operator: |
| 1090 | |
| 1091 | posts = BlogPost.objects(...).fields(slice__comments=5) |
| 1092 | posts = BlogPost.objects(...).fields(elemMatch__comments="test") |
| 1093 | |
| 1094 | :param kwargs: A set of keyword arguments identifying what to |
| 1095 | include, exclude, or slice. |
| 1096 | """ |
| 1097 | |
| 1098 | # Check for an operator and transform to mongo-style if there is |
| 1099 | operators = ["slice", "elemMatch"] |
| 1100 | cleaned_fields = [] |
| 1101 | for key, value in kwargs.items(): |
| 1102 | parts = key.split("__") |
| 1103 | if parts[0] in operators: |
| 1104 | op = parts.pop(0) |
| 1105 | value = {"$" + op: value} |
| 1106 | key = ".".join(parts) |
| 1107 | cleaned_fields.append((key, value)) |
| 1108 | |
| 1109 | # Sort fields by their values, explicitly excluded fields first, then |
| 1110 | # explicitly included, and then more complicated operators such as |
| 1111 | # $slice. |
| 1112 | def _sort_key(field_tuple): |
| 1113 | _, value = field_tuple |
| 1114 | if isinstance(value, int): |
| 1115 | return value # 0 for exclusion, 1 for inclusion |
| 1116 | return 2 # so that complex values appear last |
| 1117 | |
| 1118 | fields = sorted(cleaned_fields, key=_sort_key) |
| 1119 | |
| 1120 | # Clone the queryset, group all fields by their value, convert |
| 1121 | # each of them to db_fields, and set the queryset's _loaded_fields |
| 1122 | queryset = self.clone() |
| 1123 | for value, group in itertools.groupby(fields, lambda x: x[1]): |
| 1124 | fields = [field for field, value in group] |
| 1125 | fields = queryset._fields_to_dbfields(fields) |
| 1126 | queryset._loaded_fields += QueryFieldList( |
| 1127 | fields, value=value, _only_called=_only_called |
| 1128 | ) |
| 1129 | |
| 1130 | return queryset |
| 1131 |