from __future__ import unicode_literals import logging import yaml from django.contrib.contenttypes.models import ContentType from django.db import models from .classes import BaseTransformation logger = logging.getLogger(__name__) class TransformationManager(models.Manager): def copy(self, source, targets): """ Copy transformation from source to all targets """ content_type = ContentType.objects.get_for_model(source) # Get transformations transformations = self.filter(content_type=content_type, object_id=source.pk).values('name', 'arguments', 'order') logger.debug('source transformations: %s', transformations) # Get all targets from target QS targets_dict = map(lambda entry: {'content_type': entry[0], 'object_id': entry[1]}, zip(ContentType.objects.get_for_models(*targets).values(), targets.values_list('pk', flat=True))) logger.debug('targets: %s', targets_dict) # Combine the two results = [] for instance in targets_dict: for transformation in transformations: result = instance.copy() result.update(transformation) results.append(dict(result)) logger.debug('results: %s', results) # Bulk create for a single DB query self.bulk_create( map(lambda entry: self.model(**entry), results), ) def get_for_model(self, obj, as_classes=False): """ as_classes == True returns the transformation classes from .classes ready to be feed to the converter class """ content_type = ContentType.objects.get_for_model(obj) transformations = self.filter(content_type=content_type, object_id=obj.pk) if as_classes: result = [] for transformation in transformations: try: transformation_class = BaseTransformation.get(transformation.name) except KeyError: # Non existant transformation, but we don't raise an error logger.error('Non existant transformation: %s for %s', transformation.name, obj) else: try: result.append(transformation_class(**yaml.safe_load(transformation.arguments))) except Exception as exception: logger.error('Error while parsing transformation "%s", arguments "%s", for object "%s"; %s', transformation, transformation.arguments, obj, exception) return result else: return transformations