def get_path(self): """ Return the path as a list of prefetched objects. """ # Compile a list of IDs to prefetch for each type of model in the path to_prefetch = defaultdict(list) for node in self.path: ct_id, object_id = decompile_path_node(node) to_prefetch[ct_id].append(object_id) # Prefetch path objects using one query per model type. Prefetch related devices where appropriate. prefetched = {} for ct_id, object_ids in to_prefetch.items(): model_class = ContentType.objects.get_for_id(ct_id).model_class() queryset = model_class.objects.filter(pk__in=object_ids) if hasattr(model_class, "device"): queryset = queryset.prefetch_related("device") prefetched[ct_id] = {obj.id: obj for obj in queryset} # Replicate the path using the prefetched objects. path = [] for node in self.path: ct_id, object_id = decompile_path_node(node) path.append(prefetched[ct_id][object_id]) return path
def get_total_length(self): """ Return the sum of the length of each cable in the path. """ cable_ids = [ # Starting from the first element, every third element in the path should be a Cable decompile_path_node(self.path[i])[1] for i in range(0, len(self.path), 3) ] return Cable.objects.filter(id__in=cable_ids).aggregate(total=Sum("_abs_length"))["total"]