Django-import-Export post_save调用了两次



我创建了一个从AbstractUser子类化的自定义用户,以及一个post_save信号和一个打印新用户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))

当我通过管理界面创建新用户时,接收器被调用一次。当我使用django-import-export导入用户时,接收器被调用两次:一次是在导入文件的初始Submit之后,然后在Confirm Import之后再次调用。 浏览代码,我看到它会在dry_run中创建用户,回滚事务并再次创建它。但是我如何在接收器中判断它是否是试运行?

我正在使用Python 3.6,Django 3.0.3,django-import-export 2.0.1

看起来 django-import-export 在导入确认时触发post_save,然后在导入后再次触发。使用on_commit的建议对我不起作用,因此我不得不停止使用信号。不过有ModelResource.after_save_instace方法:

class MyResource(ModelResource):
class Meta:
model = MyModel

def after_save_instance(
self, instance: MyModel, using_transactions: bool, dry_run: bool,
):
super().after_save_instance(instance, using_transactions, dry_run)
if dry_run is False:
my_model_on_save_action(instance)

我已经通过使用"试运行"标志解决了这个问题。

我的资源类如下所示:

class SentenceResource(resources.ModelResource):
def before_save_instance(self, instance, using_transactions, dry_run):
instance.dry_run = dry_run # set a temporal flag for dry-run mode
class Meta:
model = Sentence

我的信号是这样的:

@receiver(post_save, sender=Sentence)
def create_sentence(sender, instance=None, created=False, **kwargs):
if hasattr(instance, 'dry_run'):
if instance.dry_run:
return # not send to elastic search
else:
pass
if created:
...
else:
...

谢谢你。 有谁知道为什么 Django-import-export 在导入过程中对模型调用 save(( 方法两次,并使用 dry_run = True 进行确认? 据我所知,导入数据只是临时保存到内存或磁盘中的临时位置,实际上并没有写入数据库。

为了使我的解决方案正常工作,我需要在模型资源上使用after_save_instance使用上述解决方案,但是... 对于使用 CreateView 添加的单个实例,我需要调整我的form_valid方法,以便在创建模型的新实例时执行操作:

class MyCreateView(CreateView): 
model = MyModel
fields = [ 'email', 'name']
def form_valid(self, form):
self.object = form.save()
self.object.save() 
## Perform action here like send email etc.
return HttpResponseRedirect(self.get_success_url()) 

最新更新