def handle(self, *args, **options): minx = options['minx'] miny = options['miny'] maxx = options['maxx'] maxy = options['maxy'] if minx >= maxx: raise CommandError(_('minx has to be lower than maxx')) if miny >= maxy: raise CommandError(_('miny has to be lower than maxy')) width = maxx-minx height = maxy-miny model = {'areas': Area, 'obstacles': Obstacle}[options['type']] namespaces = {'svg': 'http://www.w3.org/2000/svg'} svg = ElementTree.fromstring(options['svgfile'].read()) svg_width = float(svg.attrib['width']) svg_height = float(svg.attrib['height']) for element in svg.findall('.//svg:clipPath/..', namespaces): for clippath in element.findall('./svg:clipPath', namespaces): element.remove(clippath) for element in svg.findall('.//svg:symbol/..', namespaces): for clippath in element.findall('./svg:symbol', namespaces): element.remove(clippath) if svg.findall('.//*[@transform]'): raise CommandError(_('svg contains transform attributes. Use inkscape apply transforms.')) if model.objects.filter(space=options['space'], import_tag=options['name']).exists(): raise CommandError(_('objects with this import tag already exist in this space.')) with MapUpdate.lock(): changed_geometries.reset() for path in svg.findall('.//svg:path', namespaces): for polygon in self.parse_svg_data(path.attrib['d']): if len(polygon) < 3: continue polygon = Polygon(polygon) polygon = scale(polygon, xfact=1, yfact=-1, origin=(0, svg_height/2)) polygon = scale(polygon, xfact=width / svg_width, yfact=height / svg_height, origin=(0, 0)) polygon = translate(polygon, xoff=minx, yoff=miny) obj = model(geometry=polygon, space=options['space'], import_tag=options['name']) obj.save() MapUpdate.objects.create(type='importsvg') logger = logging.getLogger('c3nav') logger.info('Imported, map update created.') logger.info('Next step: go into the shell and edit them using ' '%s.objects.filter(space_id=%r, import_tag=%r)' % (model.__name__, options['space'].pk, options['name']))
def lock_to_edit(self, request=None): with transaction.atomic(): user = request.user if request is not None and request.user.is_authenticated else None if self.pk is not None: changeset = ChangeSet.objects.select_for_update().get(pk=self.pk) self._object_changed = False yield changeset if self._object_changed: update = changeset.updates.create(user=user, objects_changed=True) changeset.last_update = update changeset.last_change = update changeset.save() elif self.direct_editing: with MapUpdate.lock(): changed_geometries.reset() ChangeSet.objects_changed_count = 0 yield self if ChangeSet.objects_changed_count: MapUpdate.objects.create(user=user, type='direct_edit') else: yield self
def apply(self, user): with MapUpdate.lock(): changed_geometries.reset() self._clean_changes() changed_objects = self.relevant_changed_objects() created_objects = [] existing_objects = [] for changed_object in changed_objects: (created_objects if changed_object.is_created else existing_objects).append(changed_object) objects = self.get_objects(changed_objects=changed_objects) # remove slugs on all changed existing objects slugs_updated = set(changed_object.obj_pk for changed_object in existing_objects if (issubclass(changed_object.model_class, LocationSlug) and 'slug' in changed_object.updated_fields)) LocationSlug.objects.filter(pk__in=slugs_updated).update(slug=None) redirects_deleted = set(changed_object.obj_pk for changed_object in existing_objects if (issubclass(changed_object.model_class, LocationRedirect) and changed_object.deleted)) LocationRedirect.objects.filter(pk__in=redirects_deleted).delete() # create created objects created_pks = {} objects_to_create = set(created_objects) while objects_to_create: created_in_last_run = set() for created_object in objects_to_create: model = created_object.model_class pk = created_object.obj_pk # lets try to create this object obj = model() try: created_object.apply_to_instance(obj, created_pks=created_pks) except ApplyToInstanceError: continue obj.save() created_in_last_run.add(created_object) created_pks.setdefault(model, {})[pk] = obj.pk objects.setdefault(model, {})[pk] = obj objects_to_create -= created_in_last_run # update existing objects for existing_object in existing_objects: if existing_object.deleted: continue model = existing_object.model_class pk = existing_object.obj_pk obj = objects[model][pk] existing_object.apply_to_instance(obj, created_pks=created_pks) obj.save() # delete existing objects for existing_object in existing_objects: if not existing_object.deleted and not issubclass(existing_object.model_class, LocationRedirect): continue model = existing_object.model_class pk = existing_object.obj_pk obj = objects[model][pk] obj.delete() # update m2m for changed_object in changed_objects: obj = objects[changed_object.model_class][changed_object.obj_pk] for mode, updates in (('remove', changed_object.m2m_removed), ('add', changed_object.m2m_added)): for name, pks in updates.items(): field = changed_object.model_class._meta.get_field(name) pks = tuple(objects[field.related_model][pk].pk for pk in pks) getattr(getattr(obj, name), mode)(*pks) update = self.updates.create(user=user, state='applied') map_update = MapUpdate.objects.create(user=user, type='changeset') self.state = 'applied' self.last_state_update = update self.last_update = update self.map_update = map_update self.save()
def apply(self, user): with MapUpdate.lock(): changed_geometries.reset() self._clean_changes() changed_objects = self.relevant_changed_objects() created_objects = [] existing_objects = [] for changed_object in changed_objects: (created_objects if changed_object.is_created else existing_objects).append(changed_object) objects = self.get_objects(changed_objects=changed_objects) # remove slugs on all changed existing objects slugs_updated = set( changed_object.obj_pk for changed_object in existing_objects if (issubclass(changed_object.model_class, LocationSlug) and 'slug' in changed_object.updated_fields)) LocationSlug.objects.filter(pk__in=slugs_updated).update(slug=None) redirects_deleted = set( changed_object.obj_pk for changed_object in existing_objects if (issubclass(changed_object.model_class, LocationRedirect) and changed_object.deleted)) LocationRedirect.objects.filter(pk__in=redirects_deleted).delete() # create created objects created_pks = {} objects_to_create = set(created_objects) while objects_to_create: created_in_last_run = set() for created_object in objects_to_create: model = created_object.model_class pk = created_object.obj_pk # lets try to create this object obj = model() try: created_object.apply_to_instance( obj, created_pks=created_pks) except ApplyToInstanceError: continue obj.save() created_in_last_run.add(created_object) created_pks.setdefault(model, {})[pk] = obj.pk objects.setdefault(model, {})[pk] = obj objects_to_create -= created_in_last_run # update existing objects for existing_object in existing_objects: if existing_object.deleted: continue model = existing_object.model_class pk = existing_object.obj_pk obj = objects[model][pk] existing_object.apply_to_instance(obj, created_pks=created_pks) obj.save() # delete existing objects for existing_object in existing_objects: if not existing_object.deleted and not issubclass( existing_object.model_class, LocationRedirect): continue model = existing_object.model_class pk = existing_object.obj_pk obj = objects[model][pk] obj.delete() # update m2m for changed_object in changed_objects: obj = objects[changed_object.model_class][ changed_object.obj_pk] for mode, updates in (('remove', changed_object.m2m_removed), ('add', changed_object.m2m_added)): for name, pks in updates.items(): field = changed_object.model_class._meta.get_field( name) pks = tuple(objects[field.related_model][pk].pk for pk in pks) getattr(getattr(obj, name), mode)(*pks) update = self.updates.create(user=user, state='applied') map_update = MapUpdate.objects.create(user=user, type='changeset') self.state = 'applied' self.last_state_update = update self.last_update = update self.map_update = map_update self.save()