handle situation if we can't fill a dummyvalue

This commit is contained in:
Laura Klünder 2024-11-29 16:07:17 +01:00
parent 18c3faa350
commit 9b6f61438a

View file

@ -561,20 +561,26 @@ class ChangedObjectCollection(BaseSchema):
model_cls = apps.get_model('mapdata', new_operation.obj.model) model_cls = apps.get_model('mapdata', new_operation.obj.model)
if isinstance(new_operation, (CreateObjectOperation, UpdateObjectOperation)): if isinstance(new_operation, (CreateObjectOperation, UpdateObjectOperation)):
couldnt_fill_dummy = False
for field_name, value in tuple(new_operation.fields.items()): for field_name, value in tuple(new_operation.fields.items()):
if value is DummyValue: if value is DummyValue:
# if there's a dummy value to fill, we need to find a dummy value
field = model_cls._meta.get_field(field_name) field = model_cls._meta.get_field(field_name)
if field.null: if field.null:
# if it's nullable, we can just null it, todo: will it even be a dummy value then?
new_operation.fields[field_name] = None new_operation.fields[field_name] = None
continue continue
if field.is_relation: if field.is_relation:
# for a relation, we will try to find a valid other object to reference
if available_model_ids.get(field.related_model._meta.model_name) is None: if available_model_ids.get(field.related_model._meta.model_name) is None:
# find available model ids, we only query these once for less queries
available_model_ids[field.related_model._meta.model_name] = frozenset( available_model_ids[field.related_model._meta.model_name] = frozenset(
field.related_model.objects.values_list('pk', flat=True) field.related_model.objects.values_list('pk', flat=True)
) )
if field.unique: if field.unique:
# if the field is unique we need to fin a value that isn't occupied
# and, to be sure, that we haven't used as a dummyvalue before
if dummy_unique_value_avoid.get(new_operation.obj.model, {}).get(field_name) is None: if dummy_unique_value_avoid.get(new_operation.obj.model, {}).get(field_name) is None:
dummy_unique_value_avoid.setdefault( dummy_unique_value_avoid.setdefault(
new_operation.obj.model, {} new_operation.obj.model, {}
@ -592,10 +598,12 @@ class ChangedObjectCollection(BaseSchema):
else: else:
choices = available_model_ids[field.related_model._meta.model_name] choices = available_model_ids[field.related_model._meta.model_name]
if not choices: if not choices:
raise NotImplementedError # todo: inform user about impossibility couldnt_fill_dummy = True
break
dummy_value = next(iter(choices)) dummy_value = next(iter(choices))
else: else:
if field.unique: if field.unique:
# otherwise, an non-relational field needs a unique value
if dummy_unique_value_avoid.get(new_operation.obj.model, {}).get(field_name) is None: if dummy_unique_value_avoid.get(new_operation.obj.model, {}).get(field_name) is None:
dummy_unique_value_avoid.setdefault( dummy_unique_value_avoid.setdefault(
new_operation.obj.model, {} new_operation.obj.model, {}
@ -609,7 +617,11 @@ class ChangedObjectCollection(BaseSchema):
) )
) )
else: else:
occupied = frozenset() # this shouldn't happen, because dummy values are only used by non-relation fields
# for unique constraints
raise NotImplementedError
# generate a value that works
if isinstance(field, (SlugField, CharField)): if isinstance(field, (SlugField, CharField)):
new_val = "dummyvalue" new_val = "dummyvalue"
while new_val in occupied: while new_val in occupied:
@ -623,11 +635,16 @@ class ChangedObjectCollection(BaseSchema):
raise NotImplementedError raise NotImplementedError
dummy_value = new_val dummy_value = new_val
# store the dummyvalue so we can tell the user about it
problems.get_object(new_operation.obj).dummy_values[field_name] = dummy_value problems.get_object(new_operation.obj).dummy_values[field_name] = dummy_value
else: # not a dummy value else:
# we have set this field to a non-dummy value, if we used one before we can forget it
problems.get_object(new_operation.obj).dummy_values.pop(field_name, None) problems.get_object(new_operation.obj).dummy_values.pop(field_name, None)
if couldnt_fill_dummy:
continue # if we couldn't fill a dummy value this operation is not doable, skip it
# construct new situation # construct new situation
new_situation = situation.model_copy(deep=True) new_situation = situation.model_copy(deep=True)