Add partial field saves for models - #864
Conversation
|
@abrookins I've pushed f4f0caf to address the search-reader part of the latest Bugbot finding. All 344 async/sync HashModel and JsonModel tests pass locally, as do Ruff lint/format, the configured mypy target, and Bandit. The indexed numeric case is still unresolved, and I'd appreciate your guidance on the intended null-storage behavior. On Redis Stack (Redis 7.4.7), writing I checked replacing the field with
Nullable strings have the same default/missing-field distinction. Treating every absent nullable field as None would change normal defaults and expiration behavior as well. Would you prefer this PR to reject unsupported None updates explicitly until a general null-storage design is agreed, or should it introduce separate null metadata to preserve explicit None for these fields? I'd prefer to agree on the representation before expanding #772 into a storage-format change. I have left the write representation unchanged for now, so this does not resolve the whole Bugbot comment yet. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
Reviewed by Cursor Bugbot for commit f4f0caf. Configure here.
| # field name) to the target value. | ||
| setattr(obj, target_field, value) | ||
| await self.save() | ||
|
|
There was a problem hiding this comment.
Nested updates crash on null parents
Medium Severity
Nested JSON writes accept Optional embedded paths during validation, then fail when the parent is None. update() and FindQuery.update() hit setattr on None, and save(update_fields=...) subscripts None while walking the dumped document, so a bulk nested update aborts before the pipeline executes.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit f4f0caf. Configure here.


Summary
Testing
Closes #772
Note
Medium Risk
Changes core save/update persistence for all Hash and JSON models; incorrect partial-write semantics could cause lost concurrent updates or unexpected
Nonereturns, though behavior is covered by extensive new tests.Overview
Adds
save(update_fields=...)onHashModelandJsonModelso callers can persist only named fields instead of rewriting the whole Redis record.update()andFindQuery.update()now go through a shared_update_with_pipelinepath that applies the same partial writes (including nestedaddress__citypaths on JSON models).Partial updates are existence-gated: Lua scripts run
HSETor multipleJSON.SETonly when the key still exists; otherwisesave()returnsNoneinstead of creating a stub document. Hash partial saves can clear optional fields by storing explicitNoneas"", withfrom_redisaligned to decode those back likeHashModel.get().Validation is tightened: primary key updates are rejected,
exclude=Truefields cannot be updated,update_fieldscannot be combined withnx/xx, and nested update paths are checked viamodel_fields(includingT | None).Reviewed by Cursor Bugbot for commit f4f0caf. Bugbot is set up for automated code reviews on this repo. Configure here.