Django-import-export: A way to create objects in bulk?

Created on 5 Apr 2019  路  4Comments  路  Source: django-import-export/django-import-export

@bmihelac @andrewgy8 @yozlet

Is there a way to create objects in bulk during an import? Maybe overriding a method?

The default way of calling save for every row is slow when you have a big dataset to import. However, it is extremely slow when that data set also has foreign keys.

There was never an answer to #588

performance question

Most helpful comment

This is a very quick hack I tried and seemed to work. Not sure the implications in other features like validation, database integrity errores and stuff like that. It should work as expected but test and use at your own risk. I didn't use this in the end that's why I didn't continue testing.

class BulkSaveMixin:
    bulk_instances = []
    bulk_m2m_fields = []

    def save_instance(self, instance, using_transactions=True, dry_run=False):
        self.before_save_instance(instance, using_transactions, dry_run)
        if not using_transactions and dry_run:
            # we don't have transactions and we want to do a dry_run
            pass
        else:
            self.bulk_instances.append(instance)
        self.after_save_instance(instance, using_transactions, dry_run)

    def save_m2m(self, obj, data, using_transactions, dry_run):
        if not using_transactions and dry_run:
            # we don't have transactions and we want to do a dry_run
            pass
        else:
            for field in self.get_import_fields():
                if not isinstance(field.widget, ManyToManyWidget):
                    continue
                self.bulk_m2m_fields.append((field, obj, data, True))

    def after_import(self, dataset, result, using_transactions, dry_run, **kwargs):
        self._meta.model.objects.bulk_create(self.bulk_instances)
        for m2m_field in self.bulk_m2m_fields:
            self.import_field(*m2m_field)

All 4 comments

Does anybody have a solution?

This is a very quick hack I tried and seemed to work. Not sure the implications in other features like validation, database integrity errores and stuff like that. It should work as expected but test and use at your own risk. I didn't use this in the end that's why I didn't continue testing.

class BulkSaveMixin:
    bulk_instances = []
    bulk_m2m_fields = []

    def save_instance(self, instance, using_transactions=True, dry_run=False):
        self.before_save_instance(instance, using_transactions, dry_run)
        if not using_transactions and dry_run:
            # we don't have transactions and we want to do a dry_run
            pass
        else:
            self.bulk_instances.append(instance)
        self.after_save_instance(instance, using_transactions, dry_run)

    def save_m2m(self, obj, data, using_transactions, dry_run):
        if not using_transactions and dry_run:
            # we don't have transactions and we want to do a dry_run
            pass
        else:
            for field in self.get_import_fields():
                if not isinstance(field.widget, ManyToManyWidget):
                    continue
                self.bulk_m2m_fields.append((field, obj, data, True))

    def after_import(self, dataset, result, using_transactions, dry_run, **kwargs):
        self._meta.model.objects.bulk_create(self.bulk_instances)
        for m2m_field in self.bulk_m2m_fields:
            self.import_field(*m2m_field)

AFAIK, there is not a way currently to create objects in bulk. The current implementation creates objects one by one.

A quick scan of the solution @honi posted looks like it may work, but since I have not tried it myself, I can not say for sure.

If someone tries the solution above, and it does work as expected, please let us know. And if you feel up for it, write some tests and submit a PR!

I have achieved some decent performance improvements for bulk creates of new rows. Some notes here

See also #1030, #730, #588

Was this page helpful?
0 / 5 - 0 ratings

Related issues

davemerwin picture davemerwin  路  5Comments

s-y picture s-y  路  6Comments

daysleeper1980 picture daysleeper1980  路  6Comments

lmeroc picture lmeroc  路  3Comments

aidanlister picture aidanlister  路  5Comments