we will reuse IDs, instead of having temporary ones
This commit is contained in:
parent
71789e7f41
commit
77ce6fef2e
1 changed files with 9 additions and 46 deletions
|
@ -21,16 +21,15 @@ except ImportError:
|
|||
|
||||
|
||||
FieldValuesDict: TypeAlias = dict[str, Any]
|
||||
ExistingOrCreatedID: TypeAlias = int # negative = temporary ID of created object
|
||||
|
||||
|
||||
class ObjectReference(BaseSchema):
|
||||
model_config = ConfigDict(frozen=True)
|
||||
model: str
|
||||
id: ExistingOrCreatedID
|
||||
id: int
|
||||
|
||||
@classmethod
|
||||
def simple_from_instance(cls, instance: Model):
|
||||
def from_instance(cls, instance: Model):
|
||||
"""
|
||||
This method will not convert the ID yet!
|
||||
"""
|
||||
|
@ -121,39 +120,13 @@ class ChangesetOverlayManager:
|
|||
new_changes: bool = False
|
||||
pre_change_values: dict[ObjectReference, FieldValuesDict] = field(default_factory=dict)
|
||||
|
||||
# maps negative IDs of created objects to the ID during the current transaction
|
||||
mapped_ids: dict[ObjectReference, int] = field(default_factory=dict)
|
||||
|
||||
# maps IDs as used during the current transaction to the negative IDs
|
||||
reverse_mapped_ids: dict[ObjectReference, int] = field(default_factory=dict)
|
||||
|
||||
def ref_lookup(self, ref: ObjectReference):
|
||||
local_value = self.mapped_ids.get(ref, None)
|
||||
return ref if local_value is None else ObjectReference(model=ref.model, id=local_value)
|
||||
|
||||
def reverse_ref_lookup(self, ref: ObjectReference):
|
||||
created_value = self.reverse_mapped_ids.get(ref, None)
|
||||
return ref if created_value is None else ObjectReference(model=ref.model, id=created_value)
|
||||
|
||||
def get_model_field_values(self, instance: Model) -> FieldValuesDict:
|
||||
values = json.loads(serializers.serialize("json", [instance]))[0]["fields"]
|
||||
for field in instance._meta.get_fields():
|
||||
if field.name not in values:
|
||||
continue
|
||||
if isinstance(field, (OneToOneField, ForeignKey)):
|
||||
value = values[field.name]
|
||||
if value is not None:
|
||||
values[field.name] = self.reverse_ref_lookup(
|
||||
ObjectReference(model=field.model._meta.model_name, id=value)
|
||||
).id
|
||||
return values
|
||||
return json.loads(serializers.serialize("json", [instance]))[0]["fields"]
|
||||
|
||||
def handle_pre_change_instance(self, sender: Type[Model], instance: Model, **kwargs):
|
||||
if instance.pk is None:
|
||||
return
|
||||
ref = ObjectReference.simple_from_instance(instance)
|
||||
if ref in self.reverse_mapped_ids:
|
||||
return
|
||||
ref = ObjectReference.from_instance(instance)
|
||||
if ref not in self.pre_change_values and ref not in self.changes.prev_values:
|
||||
self.pre_change_values[ref] = self.get_model_field_values(
|
||||
instance._meta.model.objects.get(pk=instance.pk)
|
||||
|
@ -163,16 +136,10 @@ class ChangesetOverlayManager:
|
|||
update_fields: set | None, **kwargs):
|
||||
field_values = self.get_model_field_values(instance)
|
||||
|
||||
ref = ObjectReference.from_instance(instance)
|
||||
|
||||
if created:
|
||||
created_id = min([change.obj.id for change in self.changes
|
||||
if isinstance(change, CreateObjectChange)], default=0)-1
|
||||
model_name = instance._meta.model_name
|
||||
self.mapped_ids[ObjectReference(model=model_name, id=created_id)] = instance.pk
|
||||
self.reverse_mapped_ids[ObjectReference(model=model_name, id=instance.pk)] = created_id
|
||||
self.changes.changes.append(CreateObjectChange(
|
||||
obj=ObjectReference(model=instance._meta.model_name, id=created_id),
|
||||
fields=field_values
|
||||
))
|
||||
self.changes.changes.append(CreateObjectChange(obj=ref, fields=field_values))
|
||||
from pprint import pprint
|
||||
pprint(self.changes)
|
||||
return
|
||||
|
@ -180,20 +147,16 @@ class ChangesetOverlayManager:
|
|||
if update_fields:
|
||||
field_values = {name: value for name, value in field_values.items() if name in update_fields}
|
||||
|
||||
ref = self.reverse_ref_lookup(ObjectReference.simple_from_instance(instance))
|
||||
pre_change_values = self.pre_change_values.pop(ref, None)
|
||||
if pre_change_values:
|
||||
self.changes.prev_values[ref] = pre_change_values
|
||||
self.changes.prev_reprs[ref] = str(instance)
|
||||
self.changes.changes.append(UpdateObjectChange(
|
||||
obj=ref,
|
||||
fields=field_values
|
||||
))
|
||||
self.changes.changes.append(UpdateObjectChange(obj=ref, fields=field_values))
|
||||
from pprint import pprint
|
||||
pprint(self.changes)
|
||||
|
||||
def handle_post_delete(self, sender: Type[Model], instance: Model, **kwargs):
|
||||
ref = self.reverse_ref_lookup(ObjectReference.simple_from_instance(instance))
|
||||
ref = ObjectReference.from_instance(instance)
|
||||
pre_change_values = self.pre_change_values.pop(ref, None)
|
||||
if pre_change_values:
|
||||
self.changes.prev_values[ref] = pre_change_values
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue