Skip to content

Commit 84402cd

Browse files
committed
Fix single-valued UID reference fields not settable through the JSON API
The UIDReferenceFieldMixin always passed a list to the field setter, even for single-valued fields. AT UIDReferenceField validators reject a list value ('[...] is not supported'), so assigning e.g. a Sample's Specification, Batch or SamplePoint through the API failed. Unwrap the list to a scalar (or None to clear) for non multi-valued fields, matching the classic ReferenceFieldManager.
1 parent 36a6caa commit 84402cd

2 files changed

Lines changed: 9 additions & 4 deletions

File tree

docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Changelog
1515
applied. Uninstalling from the same panel removes the PAS plugin
1616
and the per-user JWT signing secrets.
1717

18+
- #106 Fix single-valued UID reference fields not settable through the JSON API
1819
- #94 Extract registry and settings helpers to api/settings
1920
- #93 Convert api module into a package and extract user helpers
2021
- #92 Restrict /registry, /settings, /users to prevent info leaks

src/senaite/jsonapi/fieldmanagers.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -664,14 +664,18 @@ def set(self, instance, value, **kw): # noqa
664664
elif api.is_path(v):
665665
refs.append(api.get_object_by_path(v))
666666

667-
# Handle non multi valued fields
667+
# convert all references to UIDs
668+
refs = [str(api.get_uid(ref)) for ref in refs if ref]
669+
670+
# Single valued fields expect a scalar value, not a list. Passing a
671+
# list makes the field validator of e.g. an AT UIDReferenceField
672+
# reject the value with "[...] is not supported", so unwrap it here
673+
# (None clears the reference). Multi valued fields keep the list.
668674
if not self.multi_valued:
669675
if len(refs) > 1:
670676
raise ValueError("Multiple values given for single valued "
671677
"field {}".format(repr(self.field)))
672-
673-
# convert all references to UIDs
674-
refs = [str(api.get_uid(ref)) for ref in refs if ref]
678+
refs = refs[0] if refs else None
675679

676680
return self._set(instance, refs, **kw)
677681

0 commit comments

Comments
 (0)