Transform an update spec from Django-style format to Mongo format.
(_doc_cls=None, **update)
| 236 | |
| 237 | |
| 238 | def update(_doc_cls=None, **update): |
| 239 | """Transform an update spec from Django-style format to Mongo |
| 240 | format. |
| 241 | """ |
| 242 | mongo_update = {} |
| 243 | |
| 244 | for key, value in update.items(): |
| 245 | if key == "__raw__": |
| 246 | handle_raw_query(value, mongo_update) |
| 247 | continue |
| 248 | |
| 249 | parts = key.split("__") |
| 250 | |
| 251 | # if there is no operator, default to 'set' |
| 252 | if len(parts) < 3 and parts[0] not in UPDATE_OPERATORS: |
| 253 | parts.insert(0, "set") |
| 254 | |
| 255 | # Check for an operator and transform to mongo-style if there is |
| 256 | op = None |
| 257 | if parts[0] in UPDATE_OPERATORS: |
| 258 | op = parts.pop(0) |
| 259 | # Convert Pythonic names to Mongo equivalents |
| 260 | operator_map = { |
| 261 | "push_all": "pushAll", |
| 262 | "pull_all": "pullAll", |
| 263 | "dec": "inc", |
| 264 | "add_to_set": "addToSet", |
| 265 | "set_on_insert": "setOnInsert", |
| 266 | } |
| 267 | if op == "dec": |
| 268 | # Support decrement by flipping a positive value's sign |
| 269 | # and using 'inc' |
| 270 | value = -value |
| 271 | # If the operator doesn't found from operator map, the op value |
| 272 | # will stay unchanged |
| 273 | op = operator_map.get(op, op) |
| 274 | |
| 275 | match = None |
| 276 | |
| 277 | if len(parts) == 1: |
| 278 | # typical update like set__field |
| 279 | # but also allows to update a field named like a comparison operator |
| 280 | # like set__type = "something" (without clashing with the 'type' operator) |
| 281 | pass |
| 282 | elif len(parts) > 1: |
| 283 | # can be either an embedded field like set__foo__bar |
| 284 | # or a comparison operator as in pull__foo__in |
| 285 | if parts[-1] in COMPARISON_OPERATORS: |
| 286 | match = parts.pop() # e.g. pop 'in' from pull__foo__in |
| 287 | |
| 288 | # Allow to escape operator-like field name by __ |
| 289 | # e.g. in the case of an embedded foo.type field |
| 290 | # Doc.objects().update(set__foo__type="bar") |
| 291 | # see https://github.com/MongoEngine/mongoengine/pull/1351 |
| 292 | if parts[-1] == "": |
| 293 | match = parts.pop() # e.g. pop last '__' from set__foo__type__ |
| 294 | |
| 295 | if _doc_cls: |
nothing calls this directly
no test coverage detected