Skip to content

Commit 21dbad8

Browse files
committed
Adapt update function to prevent db access during transaction
1 parent 34df3b7 commit 21dbad8

File tree

1 file changed

+36
-3
lines changed

1 file changed

+36
-3
lines changed

django_features/custom_fields/serializers.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,14 @@ def get_choices(self, obj: CustomField) -> list:
5252

5353
CustomFieldData = namedtuple(
5454
"CustomFieldData",
55-
["id", "identifier", "choice_field", "multiple_choice"],
55+
[
56+
"id",
57+
"identifier",
58+
"choices",
59+
"choice_field",
60+
"multiple_choice",
61+
"serializer_field",
62+
],
5663
)
5764

5865

@@ -96,8 +103,10 @@ def get_fields(self) -> dict[str, Any]:
96103
CustomFieldData(
97104
field.id,
98105
field.identifier,
106+
field.choices,
99107
field.choice_field,
100108
field.multiple_choice,
109+
field.serializer_field,
101110
)
102111
)
103112
serialized_field = field.serializer_field
@@ -132,10 +141,34 @@ def create(self, validated_data: dict) -> Any:
132141
instance.custom_values.set(custom_values)
133142
return instance
134143

144+
def _create_or_update_custom_value(
145+
self, instance: CustomFieldBaseModel, field: CustomFieldData, value: Any
146+
) -> None:
147+
serializer_field = field.serializer_field
148+
serializer_field.run_validators(value)
149+
value = serializer_field.to_representation(value)
150+
try:
151+
value_object = instance.custom_values.select_related("field").get(
152+
field_id=field.id
153+
)
154+
value_object.value = value
155+
value_object.save()
156+
except CustomValue.DoesNotExist:
157+
value_object = CustomValue.objects.create(field_id=field.id, value=value)
158+
instance.custom_values.add(value_object)
159+
135160
def update(self, instance: Any, validated_data: dict) -> Any:
136161
for field in self._custom_fields:
162+
if field.identifier not in validated_data:
163+
continue
137164
value = validated_data.pop(field.identifier, None)
138-
if value is not None:
139-
setattr(instance, field.identifier, value)
165+
if field.choice_field:
166+
instance.custom_values.remove(*field.choices)
167+
if field.multiple_choice:
168+
instance.custom_values.add(*value)
169+
else:
170+
instance.custom_values.add(value)
171+
else:
172+
self._create_or_update_custom_value(instance, field, value)
140173
instance = super().update(instance, validated_data)
141174
return instance

0 commit comments

Comments
 (0)