generate changed objects

This commit is contained in:
Laura Klünder 2024-08-26 14:58:37 +02:00
parent 8201f431b0
commit bf14090010
2 changed files with 49 additions and 16 deletions

View file

@ -54,7 +54,6 @@ class ChangeSet(models.Model):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.changed_objects = None
self.created_objects = {} self.created_objects = {}
self.updated_existing = {} self.updated_existing = {}
@ -234,7 +233,7 @@ class ChangeSet(models.Model):
return self.can_edit(request) and self.state == 'unproposed' return self.can_edit(request) and self.state == 'unproposed'
def can_propose(self, request): def can_propose(self, request):
return self.can_edit(request) and not self.proposed and self.changed_objects_count return self.can_edit(request) and not self.proposed and self.changes.operations
def can_unpropose(self, request): def can_unpropose(self, request):
return self.author_id == request.user.pk and self.state in ('proposed', 'reproposed') return self.author_id == request.user.pk and self.state in ('proposed', 'reproposed')
@ -417,19 +416,7 @@ class ChangeSet(models.Model):
""" """
Get the number of changed objects. Get the number of changed objects.
""" """
self.fill_changes_cache() return len(self.changes.changed_objects)
count = 0
changed_locationslug_pks = set()
for model, objects in self.changed_objects.items():
if issubclass(model, LocationSlug):
if model == LocationRedirect:
continue
changed_locationslug_pks.update(objects.keys())
count += sum(1 for obj in objects.values() if not obj.is_created or not obj.deleted)
count += len(set(obj.obj.target_id
for obj in self.changed_objects.get(LocationRedirect, {}).values()) - changed_locationslug_pks)
return count
def get_changed_objects_by_model(self, model): def get_changed_objects_by_model(self, model):
if isinstance(model, str): if isinstance(model, str):
@ -446,7 +433,6 @@ class ChangeSet(models.Model):
if self.direct_editing: if self.direct_editing:
return _('Direct editing active') return _('Direct editing active')
return _('No objects changed') return _('No objects changed')
return 'something was changed' # todo: make this nice again
return (ngettext_lazy('%(num)d object changed', '%(num)d objects changed', 'num') % return (ngettext_lazy('%(num)d object changed', '%(num)d objects changed', 'num') %
{'num': self.changed_objects_count}) {'num': self.changed_objects_count})

View file

@ -111,6 +111,21 @@ DatabaseOperation = Annotated[
] ]
class ChangedManyToMany(BaseSchema):
cleared: bool = False
added: list[str] = []
removed: list[str] = []
class ChangedObject(BaseSchema):
obj: ObjectReference
repr: str
created: bool = False
deleted: bool = False
fields: FieldValuesDict = {}
m2m_changes: dict[str, ChangedManyToMany] = {}
class CollectedChanges(BaseSchema): class CollectedChanges(BaseSchema):
prev_reprs: dict[str, dict[int, str]] = {} prev_reprs: dict[str, dict[int, str]] = {}
prev_values: dict[str, dict[int, FieldValuesDict]] = {} prev_values: dict[str, dict[int, FieldValuesDict]] = {}
@ -128,6 +143,38 @@ class CollectedChanges(BaseSchema):
return CollectedChangesPrefetch(changes=self, instances=instances) return CollectedChangesPrefetch(changes=self, instances=instances)
@property
def changed_objects(self) -> list[ChangedObject]:
objects = {}
for operation in self.operations:
changed_object = objects.get(operation.obj, None)
if changed_object is None:
changed_object = ChangedObject(obj=operation.obj,
repr=self.prev_reprs[operation.obj.model][operation.obj.id])
objects[operation.obj] = changed_object
if isinstance(operation, CreateObjectOperation):
changed_object.created = True
changed_object.fields.update(operation.fields)
elif isinstance(operation, UpdateObjectOperation):
changed_object.fields.update(operation.fields)
elif isinstance(operation, DeleteObjectOperation):
changed_object.deleted = False
else:
changed_m2m = changed_object.m2m_changes.get(operation.field, None)
if changed_m2m is None:
changed_m2m = ChangedManyToMany()
changed_object.m2m_changes[operation.field] = changed_m2m
if isinstance(operation, ClearManyToManyOperation):
changed_m2m.cleared = True
changed_m2m.added = []
changed_m2m.removed = []
else:
changed_m2m.added = sorted((set(changed_m2m.added) | operation.add_values)
- operation.remove_values)
changed_m2m.removed = sorted((set(changed_m2m.removed) - operation.add_values)
| operation.remove_values)
return list(objects.values())
@dataclass @dataclass
class CollectedChangesPrefetch: class CollectedChangesPrefetch: