feat(api): Multi-valued attribute values ​​support adding and deleting

This commit is contained in:
pycook 2024-07-29 19:55:07 +08:00
parent 5d3fe652b0
commit ad1bb86daf
1 changed files with 48 additions and 23 deletions

View File

@ -235,10 +235,16 @@ class AttributeValueManager(object):
try: try:
if attr.is_list: if attr.is_list:
if isinstance(value, dict):
if value.get('op') == "delete":
continue
_value = value.get('v') or []
else:
_value = value
value_list = [self._validate(attr, i, value_table, ci=None, type_id=type_id, ci_id=ci_id, value_list = [self._validate(attr, i, value_table, ci=None, type_id=type_id, ci_id=ci_id,
type_attr=ci_attr2type_attr.get(attr.id)) type_attr=ci_attr2type_attr.get(attr.id))
for i in handle_arg_list(value)] for i in handle_arg_list(_value)]
ci_dict[key] = value_list ci_dict[key] = value_list if not isinstance(value, dict) else dict(op=value.get('op'), v=value_list)
if not value_list: if not value_list:
self._check_is_required(type_id, attr, '') self._check_is_required(type_id, attr, '')
@ -278,28 +284,47 @@ class AttributeValueManager(object):
existed_values = [(ValueTypeMap.serialize[attr.value_type](i.value) if existed_values = [(ValueTypeMap.serialize[attr.value_type](i.value) if
i.value or i.value == 0 else i.value) for i in existed_attrs] i.value or i.value == 0 else i.value) for i in existed_attrs]
# Comparison array starts from which position changes if isinstance(value, dict):
min_len = min(len(value), len(existed_values)) if value.get('op') == "add":
index = 0 for v in (value.get('v') or []):
while index < min_len: if v not in existed_values:
if value[index] != existed_values[index]: value_table.create(ci_id=ci.id, attr_id=attr.id, value=v, flush=False, commit=False)
break if not attr.is_dynamic:
index += 1 changed.append((ci.id, attr.id, OperateType.ADD, None, v, ci.type_id))
else:
has_dynamic = True
# Delete first and then add to ensure id sorting elif value.get('op') == "delete":
for idx in range(index, len(existed_attrs)): for idx, v in enumerate((value.get('v') or [])):
existed_attr = existed_attrs[idx] if v in existed_values:
existed_attr.delete(flush=False, commit=False) existed_values[idx].delete(flush=False, commit=False)
if not attr.is_dynamic: if not attr.is_dynamic:
changed.append((ci.id, attr.id, OperateType.DELETE, existed_values[idx], None, ci.type_id)) changed.append((ci.id, attr.id, OperateType.DELETE, v, None, ci.type_id))
else: else:
has_dynamic = True has_dynamic = True
for idx in range(index, len(value)): else:
value_table.create(ci_id=ci.id, attr_id=attr.id, value=value[idx], flush=False, commit=False) # Comparison array starts from which position changes
if not attr.is_dynamic: min_len = min(len(value), len(existed_values))
changed.append((ci.id, attr.id, OperateType.ADD, None, value[idx], ci.type_id)) index = 0
else: while index < min_len:
has_dynamic = True if value[index] != existed_values[index]:
break
index += 1
# Delete first and then add to ensure id sorting
for idx in range(index, len(existed_attrs)):
existed_attr = existed_attrs[idx]
existed_attr.delete(flush=False, commit=False)
if not attr.is_dynamic:
changed.append((ci.id, attr.id, OperateType.DELETE, existed_values[idx], None, ci.type_id))
else:
has_dynamic = True
for idx in range(index, len(value)):
value_table.create(ci_id=ci.id, attr_id=attr.id, value=value[idx], flush=False, commit=False)
if not attr.is_dynamic:
changed.append((ci.id, attr.id, OperateType.ADD, None, value[idx], ci.type_id))
else:
has_dynamic = True
else: else:
existed_attr = value_table.get_by(attr_id=attr.id, ci_id=ci.id, first=True, to_dict=False) existed_attr = value_table.get_by(attr_id=attr.id, ci_id=ci.id, first=True, to_dict=False)
existed_value = existed_attr and existed_attr.value existed_value = existed_attr and existed_attr.value