I asked this question on SO but have had no reply so I thought I raise an issue: https://stackoverflow.com/questions/60124600/django-import-export-post-save-called-twice
I created a custom user subclassed from AbstractUser and a post_save signal and a receiver that prints the new user's id.
@receiver(post_save, sender=CustomUser, dispatch_uid='members.models.customuser.post_save')
def post_save_custom_user(sender, instance=None, created=False, **kwargs):
if not created:
return
print('post_save_custom_user: {}'.format(instance.id))
When I create a new user via the admin interface the receiver is called once. When I import a user using django-import-export the receiver is called twice: once after the initial Submit of the import file and then again after the Confirm Import. Browsing through the code I see it creates the user in dry_run, rolls back the transaction and creates it again. But how can I tell in my receiver if it's a dry run or not?
I am using Python 3.6, Django 3.0.3, django-import-export 2.0.1
I am having the same issue,
I figured maybe 'post_import' might be helpful but I don't know how to access the created data so I can do extra things with it.
Also it is called only once after import confirmation.
from import_export.signals import post_import, post_export
@receiver(post_import, dispatch_uid='balabala...')
def _post_import(model, instance, **kwargs):
# model is the actual model instance which after import
pass
I have also resorted to using post_import. To determine newly imported data from existing data I added a status field to the model with a default of New. Then in my receiver I look for all New records and changed the status to Imported. Then to change the status for records created manually I added this to my response_add method in admin class:
def response_add(self, request, obj, post_url_continue=None):
obj.status = 'Created'
obj.save()
return super(CustomUserAdmin, self).response_add(request, obj, post_url_continue)
i am having the same issue, I am using django-elasticsearch-dsl to index new created objects into elasticsearch, but when I use django-import-export the save post_save signal is triggering twice, so it indexes the imported row twice. Is there a way to disable signals if the import is a dry-run?
I have been hit by this as well. I wouldn't expect post_save hooks to be called until I actually click "Confirm Import".
I have described detailed issue in pr, why it happens : https://github.com/django-import-export/django-import-export/pull/1176
Use this fix, inherit below class
```py
class BaseModelResource(resources.ModelResource):
save_points = []
def before_save_instance(self, instance, using_transactions, dry_run):
"""
Override to add additional logic. Does nothing by default.
Saving intermediate savepoints of txn
"""
if using_transactions and dry_run:
con = transaction.get_connection()
self.save_points.extend(con.savepoint_ids)
def after_import(self, dataset, result, using_transactions, dry_run, **kwargs):
"""
Override to add additional logic. Does nothing by default.
Manually removing commit hooks for intermediate savepoints of atomic transaction
"""
if using_transactions and dry_run:
con = transaction.get_connection()
for sid in self.save_points:
con.run_on_commit = [
(sids, func) for (sids, func) in con.run_on_commit if sid not in sids
]
super().after_import(dataset, result, using_transactions, dry_run, **kwargs)
I was recently hit by something similar to this issue and I solved it by doing something this like this https://stackoverflow.com/a/33192224/5779280 . Would adding a temporary value to the instance be a solution to this problem?
I admit its not an elegant solution, but I think it would work and should be quite simple to add to the package.