1

I have two models Image and Category related via a m2m relation (defined in Category). Images may be under several categories. The API allows to remove an image from a category. In response to that I need to remove the image when it has no categories.

I have the following:

@receiver(m2m_changed, sender=Category.images.through)
def delete_image_if_has_no_categories(sender, instance, action, reverse,
                                      model, pk_set, **kwargs):
    # we only watch reverse signal, because in other cases the images are
    # being moved or copied, so don't have to be deleted.
    if reverse and action == 'post_remove':
        if not instance.categories.exists():
            instance.delete()

I have placed several debug logs to check the code is being run. And it runs. But the images remain in the DB after the instance.delete().

I have the remove_from_category view inside a transaction.atomic, but it does not help.

Any ideas?

Update

The view call this method in our Image model:

def remove_from_category(self, category_id):
    self.categories.remove(category_id)

The view is called via a REST API like this DELETE /category/<catid>/<image-id>.

The images field in the Category model is defined like this:

class Category(MPTTModel):
    images = models.ManyToManyField(
        'Image',
        related_name='categories',
        null=True, blank=True,
    )

Would the MPTTModel be the culprit? I'm using django-mptt==0.6.0.

manu
  • 3,544
  • 5
  • 28
  • 50
  • I need to see the relevant model, view and form code too. There are many details that could cause this behaviour. – Robert Jørgensgaard Engdahl Jul 09 '14 at 20:10
  • Verify that your instance is the image and not the m2m relation itself. – Dave Jul 09 '14 at 20:16
  • @Mr.Dave I have verified the instance is the image; otherwise the `instance.categories` would raise an AttributeError, wouldn't it? – manu Jul 09 '14 at 20:19
  • @RobertJørgensgaardEngdahl I'm trying to collect the relevant parts. It's a big app. – manu Jul 09 '14 at 20:20
  • As @RobertJørgensgaardEngdahl said, it's difficult to know without at least seeing some code. Perhaps you could also post the defined m2m field in Category? That would help remove some assumptions about how you've defined the m2m. – Dave Jul 09 '14 at 20:32
  • Are you calling `image.category_set.remove(category)` ? – Dave Jul 09 '14 at 20:42
  • @Mr.Dave I've an update exposing more of the code. If more is need I'm willing to keep updating. – manu Jul 09 '14 at 22:32
  • @manu At this point I'm stumped ... sorry. If your loggers confirm that `instance.delete()` executes I can't think of a way your problem is related to the signal. – Dave Jul 09 '14 at 22:46

1 Answers1

0

I guess u can call ur method to remove when the selected item that u want delete appeas on pre_clear method (django always save the last change in ur m2m field in the pre_clear, so if the attribute is there but didnt on ur post_add this obj is being deleted, so u can force trigger ur function there

check this answer mine https://stackoverflow.com/a/39331735/6373505

Community
  • 1
  • 1
Diego Vinícius
  • 2,125
  • 1
  • 12
  • 23