do create_multiple correctly
This commit is contained in:
parent
62d1773bb0
commit
44671a12dc
10 changed files with 86 additions and 53 deletions
|
@ -655,10 +655,19 @@ class ChangedObjectCollection(BaseSchema):
|
||||||
# construct new situation
|
# 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:
|
model = apps.get_model('mapdata', new_operation.obj.model)
|
||||||
|
for parent in model._meta.get_parent_list():
|
||||||
|
if parent._meta.concrete_model is not model._meta.concrete_model:
|
||||||
|
is_multi_inheritance = True
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
is_multi_inheritance = False
|
||||||
|
|
||||||
|
if (isinstance(new_operation, CreateObjectOperation)
|
||||||
|
and new_situation.operations and not is_multi_inheritance):
|
||||||
last_operation = new_situation.operations[-1]
|
last_operation = new_situation.operations[-1]
|
||||||
if (isinstance(last_operation, CreateObjectOperation) and
|
if (isinstance(last_operation, CreateObjectOperation)
|
||||||
last_operation.obj.model == new_operation.obj.model):
|
and last_operation.obj.model == new_operation.obj.model):
|
||||||
new_situation.operations[-1] = CreateMultipleObjectsOperation(
|
new_situation.operations[-1] = CreateMultipleObjectsOperation(
|
||||||
objects=[last_operation, new_operation],
|
objects=[last_operation, new_operation],
|
||||||
)
|
)
|
||||||
|
|
|
@ -87,33 +87,19 @@ class CreateObjectOperation(BaseOperation):
|
||||||
fields: FieldValuesDict
|
fields: FieldValuesDict
|
||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
model = apps.get_model('mapdata', self.obj.model)
|
return [{
|
||||||
data = []
|
|
||||||
if issubclass(model, LocationSlug):
|
|
||||||
data.append({
|
|
||||||
"model": f"mapdata.locationslug",
|
|
||||||
"pk": self.obj.id,
|
|
||||||
"fields": {
|
|
||||||
"slug": self.fields.get("slug", None)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
values = {key: val for key, val in self.fields.items() if key != "slug"}
|
|
||||||
else:
|
|
||||||
values = self.fields
|
|
||||||
data.append({
|
|
||||||
"model": f"mapdata.{self.obj.model}",
|
"model": f"mapdata.{self.obj.model}",
|
||||||
"pk": self.obj.id,
|
"pk": self.obj.id,
|
||||||
"fields": values,
|
"fields": self.fields,
|
||||||
})
|
}]
|
||||||
return data
|
|
||||||
|
|
||||||
def apply_create(self) -> dict[ObjectReference, Model]:
|
def apply_create(self) -> dict[ObjectReference, Model]:
|
||||||
data = self.get_data()
|
data = self.get_data()
|
||||||
instances = list(serializers.deserialize("json", json.dumps(data)))
|
instances = [item.object for item in serializers.deserialize("json", json.dumps(data))]
|
||||||
for instance in instances:
|
for instance in instances[-1:]:
|
||||||
# .object. to make sure our own .save() function is called!
|
# .object. to make sure our own .save() function is called!
|
||||||
instance.object.save()
|
instance.save()
|
||||||
return {self.obj: instances[-1].object}
|
return {self.obj: instances[-1]}
|
||||||
|
|
||||||
|
|
||||||
class CreateMultipleObjectsOperation(BaseSchema):
|
class CreateMultipleObjectsOperation(BaseSchema):
|
||||||
|
@ -126,11 +112,12 @@ class CreateMultipleObjectsOperation(BaseSchema):
|
||||||
for obj in self.objects:
|
for obj in self.objects:
|
||||||
data.extend(obj.get_data())
|
data.extend(obj.get_data())
|
||||||
indexes[obj.obj] = len(data)-1
|
indexes[obj.obj] = len(data)-1
|
||||||
instances = list(serializers.deserialize("json", json.dumps(data)))
|
instances = [item.object for item in serializers.deserialize("json", json.dumps(data))]
|
||||||
# todo: actually do a create_multiple!, let's not forget about register_changed_geometries etc
|
if hasattr(instances[-1], "pre_save_changed_geometries"):
|
||||||
for instance in instances:
|
for instance in instances:
|
||||||
# .object. to make sure our own .save() function is called!
|
instance.pre_save_changed_geometries()
|
||||||
instance.object.save()
|
model = apps.get_model('mapdata', self.objects[0].obj.model)
|
||||||
|
model.objects.bulk_create(instances)
|
||||||
return {ref: instances[i] for ref, i in indexes.items()}
|
return {ref: instances[i] for ref, i in indexes.items()}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,9 @@
|
||||||
{% if changeset.description %}
|
{% if changeset.description %}
|
||||||
<p>{{ changeset.description }}</p>
|
<p>{{ changeset.description }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if changed_objects %}
|
||||||
|
<p><em>{% blocktranslate count counter=operations|length %}({{ counter }} operation in total){% plural %}({{ counter }} operations in total){% endblocktranslate %}</em></p>
|
||||||
|
{% endif %}
|
||||||
{% for obj in changed_objects %}
|
{% for obj in changed_objects %}
|
||||||
<table class="table table-condensed table-h-bordered change-group">
|
<table class="table table-condensed table-h-bordered change-group">
|
||||||
<thead>
|
<thead>
|
||||||
|
|
|
@ -233,6 +233,7 @@ def changeset_detail(request, pk):
|
||||||
'can_unreject': changeset.can_unreject(request),
|
'can_unreject': changeset.can_unreject(request),
|
||||||
'can_apply': changeset.can_apply(request),
|
'can_apply': changeset.can_apply(request),
|
||||||
'active': active,
|
'active': active,
|
||||||
|
'operations': changeset.as_operations,
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_key = '%s:%s:%s:view_data' % (changeset.cache_key_by_changes,
|
cache_key = '%s:%s:%s:view_data' % (changeset.cache_key_by_changes,
|
||||||
|
|
|
@ -133,3 +133,10 @@ class GeometryMixin(SerializableMixin):
|
||||||
if self._meta.get_field('geometry').geomtype in ('polygon', 'multipolygon'):
|
if self._meta.get_field('geometry').geomtype in ('polygon', 'multipolygon'):
|
||||||
difference = unary_union(assert_multipolygon(difference))
|
difference = unary_union(assert_multipolygon(difference))
|
||||||
return difference
|
return difference
|
||||||
|
|
||||||
|
def pre_delete_changed_geometries(self):
|
||||||
|
self.register_delete()
|
||||||
|
|
||||||
|
def delete(self, *args, **kwargs):
|
||||||
|
self.pre_delete_changed_geometries()
|
||||||
|
super().delete(*args, **kwargs)
|
||||||
|
|
|
@ -92,8 +92,11 @@ class LevelGeometryMixin(GeometryMixin):
|
||||||
Level.q_for_request(request, prefix=prefix+'level__', allow_none=allow_none)
|
Level.q_for_request(request, prefix=prefix+'level__', allow_none=allow_none)
|
||||||
)
|
)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def pre_save_changed_geometries(self):
|
||||||
self.register_change()
|
self.register_change()
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
self.pre_save_changed_geometries()
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -98,8 +98,11 @@ class SpaceGeometryMixin(GeometryMixin):
|
||||||
space = self.space
|
space = self.space
|
||||||
changed_geometries.register(space.level_id, space.geometry.intersection(unwrap_geom(self.geometry)))
|
changed_geometries.register(space.level_id, space.geometry.intersection(unwrap_geom(self.geometry)))
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def pre_save_changed_geometries(self):
|
||||||
self.register_change()
|
self.register_change()
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
self.pre_save_changed_geometries()
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,21 +185,27 @@ class ObstacleGroup(TitledMixin, models.Model):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._orig = {"color": self.color}
|
self._orig = {"color": self.color}
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
if not self._state.adding and any(getattr(self, attname) != value for attname, value in self._orig.items()):
|
|
||||||
self.register_changed_geometries()
|
|
||||||
super().save(*args, **kwargs)
|
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
|
||||||
self.register_changed_geometries()
|
|
||||||
super().delete(*args, **kwargs)
|
|
||||||
|
|
||||||
def register_changed_geometries(self):
|
def register_changed_geometries(self):
|
||||||
for obj in self.obstacles.select_related('space'):
|
for obj in self.obstacles.select_related('space'):
|
||||||
obj.register_change(force=True)
|
obj.register_change(force=True)
|
||||||
for obj in self.lineobstacles.select_related('space'):
|
for obj in self.lineobstacles.select_related('space'):
|
||||||
obj.register_change(force=True)
|
obj.register_change(force=True)
|
||||||
|
|
||||||
|
def pre_save_changed_geometries(self):
|
||||||
|
if not self._state.adding and any(getattr(self, attname) != value for attname, value in self._orig.items()):
|
||||||
|
self.register_changed_geometries()
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
self.pre_save_changed_geometries()
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
def pre_delete_changed_geometries(self):
|
||||||
|
self.register_changed_geometries()
|
||||||
|
|
||||||
|
def delete(self, *args, **kwargs):
|
||||||
|
self.pre_delete_changed_geometries()
|
||||||
|
super().delete(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Obstacle(SpaceGeometryMixin, models.Model):
|
class Obstacle(SpaceGeometryMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -289,11 +289,21 @@ class LocationGroupCategory(SerializableMixin, models.Model):
|
||||||
for group in query:
|
for group in query:
|
||||||
group.register_changed_geometries(do_query=False)
|
group.register_changed_geometries(do_query=False)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def pre_save_changed_geometries(self):
|
||||||
if not self._state.adding and any(getattr(self, attname) != value for attname, value in self._orig.items()):
|
if not self._state.adding and any(getattr(self, attname) != value for attname, value in self._orig.items()):
|
||||||
self.register_changed_geometries()
|
self.register_changed_geometries()
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
self.pre_save_changed_geometries()
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
def pre_delete_changed_geometries(self):
|
||||||
|
self.register_changed_geometries()
|
||||||
|
|
||||||
|
def delete(self, *args, **kwargs):
|
||||||
|
self.pre_delete_changed_geometries()
|
||||||
|
super().delete(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class LocationGroupManager(models.Manager):
|
class LocationGroupManager(models.Manager):
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
@ -395,13 +405,19 @@ class LocationGroup(Location, models.Model):
|
||||||
def order(self):
|
def order(self):
|
||||||
return (1, self.category.priority, self.priority)
|
return (1, self.category.priority, self.priority)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def pre_save_changed_geometries(self):
|
||||||
if not self._state.adding and any(getattr(self, attname) != value for attname, value in self._orig.items()):
|
if not self._state.adding and any(getattr(self, attname) != value for attname, value in self._orig.items()):
|
||||||
self.register_changed_geometries()
|
self.register_changed_geometries()
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
self.pre_save_changed_geometries()
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def pre_delete_changed_geometries(self):
|
||||||
self.register_changed_geometries()
|
self.register_changed_geometries()
|
||||||
|
|
||||||
|
def delete(self, *args, **kwargs):
|
||||||
|
self.pre_delete_changed_geometries()
|
||||||
super().delete(*args, **kwargs)
|
super().delete(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -95,12 +95,18 @@ class ThemeLocationGroupBackgroundColor(models.Model):
|
||||||
fill_color = models.CharField(max_length=32, null=True, blank=True)
|
fill_color = models.CharField(max_length=32, null=True, blank=True)
|
||||||
border_color = models.CharField(max_length=32, null=True, blank=True)
|
border_color = models.CharField(max_length=32, null=True, blank=True)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def pre_save_changed_geometries(self):
|
||||||
self.location_group.register_changed_geometries()
|
self.location_group.register_changed_geometries()
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
self.pre_save_changed_geometries()
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def pre_delete_changed_geometries(self):
|
||||||
self.location_group.register_changed_geometries()
|
self.location_group.register_changed_geometries()
|
||||||
|
|
||||||
|
def delete(self, *args, **kwargs):
|
||||||
|
self.pre_delete_changed_geometries()
|
||||||
super().delete(*args, **kwargs)
|
super().delete(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
8
src/c3nav/mapdata/utils/cache/changes.py
vendored
8
src/c3nav/mapdata/utils/cache/changes.py
vendored
|
@ -75,10 +75,6 @@ class GeometryChangeTracker:
|
||||||
changed_geometries = GeometryChangeTracker() # todo: no longer needed if we use the overlay stuff
|
changed_geometries = GeometryChangeTracker() # todo: no longer needed if we use the overlay stuff
|
||||||
|
|
||||||
|
|
||||||
def geometry_deleted(sender, instance, **kwargs):
|
|
||||||
instance.register_delete()
|
|
||||||
|
|
||||||
|
|
||||||
def locationgroup_changed(sender, instance, action, reverse, model, pk_set, using, **kwargs):
|
def locationgroup_changed(sender, instance, action, reverse, model, pk_set, using, **kwargs):
|
||||||
if action not in ('post_add', 'post_remove', 'post_clear'):
|
if action not in ('post_add', 'post_remove', 'post_clear'):
|
||||||
return
|
return
|
||||||
|
@ -97,10 +93,6 @@ def locationgroup_changed(sender, instance, action, reverse, model, pk_set, usin
|
||||||
|
|
||||||
|
|
||||||
def register_signals():
|
def register_signals():
|
||||||
from c3nav.mapdata.models.geometry.base import GeometryMixin
|
|
||||||
for model in get_submodels(GeometryMixin):
|
|
||||||
post_delete.connect(geometry_deleted, sender=model)
|
|
||||||
|
|
||||||
from c3nav.mapdata.models.locations import SpecificLocation
|
from c3nav.mapdata.models.locations import SpecificLocation
|
||||||
for model in get_submodels(SpecificLocation):
|
for model in get_submodels(SpecificLocation):
|
||||||
m2m_changed.connect(locationgroup_changed, sender=model.groups.through)
|
m2m_changed.connect(locationgroup_changed, sender=model.groups.through)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue