def import_item(self, data): """ function used by import_data """ what = 'noop' # remove the JSON _id (may still be there if called directly) data.pop('_id', None) # add fields/etc. data = self.apply_transformers(data) data = self.prepare_for_db(data) try: obj = self.get_object(data) except self.model_class.DoesNotExist: obj = None # remove pupa_id which does not belong in the OCD data models pupa_id = data.pop('pupa_id', None) # pull related fields off related = {} for field in self.related_models: related[field] = data.pop(field) # obj existed, check if we need to do an update if obj: if obj.id in self.json_to_db_id.values(): raise DuplicateItemError(data, obj, related.get('sources', [])) # check base object for changes for key, value in data.items(): if getattr(obj, key) != value and key not in obj.locked_fields: setattr(obj, key, value) what = 'update' updated = self._update_related(obj, related, self.related_models) if updated: what = 'update' if what == 'update': obj.save() # need to create the data else: what = 'insert' try: obj = self.model_class.objects.create(**data) except Exception as e: raise DataImportError('{} while importing {} as {}'.format( e, data, self.model_class)) self._create_related(obj, related, self.related_models) if pupa_id: Identifier.objects.get_or_create( identifier=pupa_id, jurisdiction_id=self.jurisdiction_id, defaults={'content_object': obj}) return obj.id, what
def _create_related(self, obj, related, subfield_dict): """ create DB objects related to a base object obj: a base object to create related related: dict mapping field names to lists of related objects subfield_list: where to get the next layer of subfields """ for field, items in related.items(): subobjects = [] all_subrelated = [] Subtype, reverse_id_field, subsubdict = subfield_dict[field] for order, item in enumerate(items): # pull off 'subrelated' (things that are related to this obj) subrelated = {} for subfield in subsubdict: subrelated[subfield] = item.pop(subfield) if field in self.preserve_order: item['order'] = order item[reverse_id_field] = obj.id try: subobjects.append(Subtype(**item)) all_subrelated.append(subrelated) except Exception as e: raise DataImportError('{} while importing {} as {}'.format( e, item, Subtype)) # add all subobjects at once (really great for actions & votes) try: Subtype.objects.bulk_create(subobjects) except Exception as e: raise DataImportError('{} while importing {} as {}'.format( e, subobjects, Subtype)) # after import the subobjects, import their subsubobjects for subobj, subrel in zip(subobjects, all_subrelated): self._create_related(subobj, subrel, subsubdict)
def import_item(self, data): """ function used by import_data """ what = 'noop' # remove the JSON _id (may still be there if called directly) data.pop('_id', None) # add fields/etc. data = self.prepare_for_db(data) try: obj = self.get_object(data) except self.model_class.DoesNotExist: obj = None # pull related fields off related = {} for field in self.related_models: related[field] = data.pop(field) # obj existed, check if we need to do an update if obj: if obj.id in self.json_to_db_id.values(): raise DuplicateItemError(data, obj) # check base object for changes for key, value in data.items(): if getattr(obj, key) != value and key not in obj.locked_fields: setattr(obj, key, value) what = 'update' updated = self._update_related(obj, related, self.related_models) if updated: what = 'update' if what == 'update': obj.save() # need to create the data else: what = 'insert' try: obj = self.model_class.objects.create(**data) except TypeError as e: raise DataImportError('{} while importing {} as {}'.format(e, data, self.model_class)) self._create_related(obj, related, self.related_models) return obj.id, what