0

Using Django: 1.10

Issue: Turn off pre_delete signal and receiver sometimes

I want to use pre_delete to delete other related records for a model.

And not call it at certain times even when I do want to delete the main model

What did I try?

I tried overriding the delete function in the main model PalletContent like this:

def delete(self, *args, **kwargs):
    self.auto_delete_line_item = False
    if 'auto_delete_line_item' in kwargs:
        self.auto_delete_line_item = kwargs['auto_delete_line_item']
        del kwargs['auto_delete_line_item']

    return super(PalletContent, self).delete(*args, **kwargs)

And then in the pre_delete

@receiver(pre_delete, sender=PalletContent)
def auto_delete_line_item(sender, instance, **kwargs):
    if instance.auto_delete_line_item:
        EntryFormHelper.remove_entry_form_line_item_from_pallet_content(
            pallet_content=instance)
        ExitFormHelper.remove_exit_form_line_item_from_pallet_content_if_any(
            pallet_content=instance)

And then in the appropriate calls:

I expect this to activate the pre_delete: pallet_content.delete(auto_delete_line_item=True)

I expect this not to activate the pre_delete: pallet.pallet_contents.all().delete()

What I got back was:

 File "/usr/../signals.py", line 31, in auto_delete_line_item
    if instance.auto_delete_line_item:
AttributeError: 'PalletContent' object has no attribute 'auto_delete_line_item'
Kim Stacks
  • 10,202
  • 35
  • 151
  • 282
  • If you can override the `delete()` method, you could just delete the related objects there, and remove the signal. – Alasdair Nov 17 '17 at 13:02
  • I read that it’s better to use signals rather than override the delete method because bulk delete might not call the override delete method – Kim Stacks Nov 17 '17 at 13:28
  • If you use `queryset.delete()`, then `self.auto_delete_line_item` isn't going to be set, so you need to change your `auto_delete_line_item` method to handle that. For example, you could use `if getattr(instance, 'auto_delete_line_item', False):` instead of `if instance.auto_delete_line_item:`. – Alasdair Nov 17 '17 at 13:32
  • Thanks it worked. But is this the best way to turn off signals occasionally? – Kim Stacks Nov 17 '17 at 13:46
  • I just realised that ur suggestion also means that if I use queryset to bulk delete and I wish to turn on the signal method it won’t work. Am I right? – Kim Stacks Nov 17 '17 at 13:55
  • You haven't shown any code that would allow you to 'turn on' the signal method with the `queryset.delete()` method. – Alasdair Nov 17 '17 at 13:58
  • You’re right I don’t have code like that. I am asking in a general way if there is something that allows turning on or off signal receiver methods on the fly while still able to use queryset or model delete method. – Kim Stacks Nov 17 '17 at 14:02
  • Have a look [at this question](https://stackoverflow.com/questions/2209159/disconnect-signals-for-models-and-reconnect-in-django). I'm still not convinced that you need signals here. If you need to override `instance.delete()` and `queryset.delete()` to provide a way to disable the signal, then you could just do the work there. – Alasdair Nov 17 '17 at 14:13

0 Answers0