as_operations can now create a create_multiple
This commit is contained in:
parent
99085a0646
commit
2749091168
2 changed files with 43 additions and 7 deletions
|
@ -17,7 +17,7 @@ from pydantic.config import ConfigDict
|
||||||
from c3nav.api.schema import BaseSchema
|
from c3nav.api.schema import BaseSchema
|
||||||
from c3nav.editor.operations import DatabaseOperationCollection, CreateObjectOperation, UpdateObjectOperation, \
|
from c3nav.editor.operations import DatabaseOperationCollection, CreateObjectOperation, UpdateObjectOperation, \
|
||||||
DeleteObjectOperation, ClearManyToManyOperation, FieldValuesDict, ObjectReference, PreviousObjectCollection, \
|
DeleteObjectOperation, ClearManyToManyOperation, FieldValuesDict, ObjectReference, PreviousObjectCollection, \
|
||||||
DatabaseOperation, ObjectID, FieldName, ModelName
|
DatabaseOperation, ObjectID, FieldName, ModelName, CreateMultipleObjectsOperation
|
||||||
from c3nav.mapdata.fields import I18nField
|
from c3nav.mapdata.fields import I18nField
|
||||||
|
|
||||||
|
|
||||||
|
@ -514,10 +514,25 @@ class ChangedObjectCollection(BaseSchema):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
new_operation.fields[field_name] = new_val
|
new_operation.fields[field_name] = new_val
|
||||||
|
|
||||||
# construct new situation # todo: merge create operations one day
|
# construct new situation
|
||||||
new_situation = situation.model_copy(deep=True)
|
new_situation = situation.model_copy(deep=True)
|
||||||
|
|
||||||
|
if isinstance(new_operation, CreateObjectOperation) and new_situation.operations:
|
||||||
|
last_operation = new_situation.operations[-1]
|
||||||
|
if (isinstance(last_operation, CreateObjectOperation) and
|
||||||
|
last_operation.obj.model == new_operation.obj.model):
|
||||||
|
new_situation.operations[-1] = CreateMultipleObjectsOperation(
|
||||||
|
objects=[last_operation, new_operation],
|
||||||
|
)
|
||||||
|
elif (isinstance(last_operation, CreateMultipleObjectsOperation) and
|
||||||
|
last_operation.objects[-1].obj.model == new_operation.obj.model):
|
||||||
|
last_operation.objects.append(new_operation)
|
||||||
|
else:
|
||||||
|
new_situation.operations.append(new_operation)
|
||||||
|
else:
|
||||||
|
new_situation.operations.append(new_operation)
|
||||||
|
|
||||||
new_situation.remaining_operations_with_dependencies.pop(i)
|
new_situation.remaining_operations_with_dependencies.pop(i)
|
||||||
new_situation.operations.append(new_operation)
|
|
||||||
new_situation.remaining_operations_with_dependencies.extend(new_remaining_operations)
|
new_situation.remaining_operations_with_dependencies.extend(new_remaining_operations)
|
||||||
new_situation.operation_uids = new_situation.operation_uids | uids_to_add
|
new_situation.operation_uids = new_situation.operation_uids | uids_to_add
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ class CreateObjectOperation(BaseOperation):
|
||||||
type: Literal["create"] = "create"
|
type: Literal["create"] = "create"
|
||||||
fields: FieldValuesDict
|
fields: FieldValuesDict
|
||||||
|
|
||||||
def apply_create(self) -> Model:
|
def get_data(self):
|
||||||
model = apps.get_model('mapdata', self.obj.model)
|
model = apps.get_model('mapdata', self.obj.model)
|
||||||
data = []
|
data = []
|
||||||
if issubclass(model, LocationSlug):
|
if issubclass(model, LocationSlug):
|
||||||
|
@ -104,10 +104,30 @@ class CreateObjectOperation(BaseOperation):
|
||||||
"pk": self.obj.id,
|
"pk": self.obj.id,
|
||||||
"fields": values,
|
"fields": values,
|
||||||
})
|
})
|
||||||
|
return data
|
||||||
|
|
||||||
|
def apply_create(self) -> dict[ObjectReference, Model]:
|
||||||
|
data = self.get_data()
|
||||||
instances = list(serializers.deserialize("json", json.dumps(data)))
|
instances = list(serializers.deserialize("json", json.dumps(data)))
|
||||||
for instance in instances:
|
for instance in instances:
|
||||||
instance.save(save_m2m=False)
|
instance.save(save_m2m=False)
|
||||||
return instances[-1].object
|
return {self.obj: instances[-1].object}
|
||||||
|
|
||||||
|
|
||||||
|
class CreateMultipleObjectsOperation(BaseSchema):
|
||||||
|
type: Literal["create"] = "create_multiple"
|
||||||
|
objects: list[CreateObjectOperation] = []
|
||||||
|
|
||||||
|
def apply_create(self) -> dict[ObjectReference, Model]:
|
||||||
|
indexes = {}
|
||||||
|
data = []
|
||||||
|
for obj in self.objects:
|
||||||
|
data.extend(obj.get_data())
|
||||||
|
indexes[obj.obj] = len(data)-1
|
||||||
|
instances = list(serializers.deserialize("json", json.dumps(data)))
|
||||||
|
for instance in instances:
|
||||||
|
instance.save(save_m2m=False)
|
||||||
|
return {ref: instances[i] for ref, i in indexes.items()}
|
||||||
|
|
||||||
|
|
||||||
class UpdateObjectOperation(BaseOperation):
|
class UpdateObjectOperation(BaseOperation):
|
||||||
|
@ -179,6 +199,7 @@ class ClearManyToManyOperation(BaseOperation):
|
||||||
DatabaseOperation = Annotated[
|
DatabaseOperation = Annotated[
|
||||||
Union[
|
Union[
|
||||||
CreateObjectOperation,
|
CreateObjectOperation,
|
||||||
|
CreateMultipleObjectsOperation,
|
||||||
UpdateObjectOperation,
|
UpdateObjectOperation,
|
||||||
DeleteObjectOperation,
|
DeleteObjectOperation,
|
||||||
UpdateManyToManyOperation,
|
UpdateManyToManyOperation,
|
||||||
|
@ -221,8 +242,8 @@ class PrefetchedDatabaseOperationCollection:
|
||||||
def apply(self):
|
def apply(self):
|
||||||
# todo: what if unique constraint error occurs?
|
# todo: what if unique constraint error occurs?
|
||||||
for operation in self.operations:
|
for operation in self.operations:
|
||||||
if isinstance(operation, CreateObjectOperation):
|
if isinstance(operation, (CreateObjectOperation, CreateMultipleObjectsOperation)):
|
||||||
self.instances[operation.obj] = operation.apply_create()
|
self.instances.update(operation.apply_create())
|
||||||
else:
|
else:
|
||||||
prev_obj = self.operations.prev.get(operation.obj)
|
prev_obj = self.operations.prev.get(operation.obj)
|
||||||
if prev_obj is None:
|
if prev_obj is None:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue