Question

This is my models.py:

def set_image(instance):
    return Image.objects.filter(user=instance.user)[0]

class User(models.Model):
    user = models.CharField(max_length=50)

class Image(models.Model):
    user = models.ForeignKey(User)
    image = models.ImageField(upload_to='media')

class Item(models.Model):
    user = models.ForeignKey(User)
    image = models.ForeignKey(
        Image,
        blank=True,
        null=True,
        on_delete=models.SET(set_image)
    )

When I delete an 'Image', it's related 'Item' calls set_image, which returns an error, because models.SET doesn't pass the instance to the callable. How can I change this behavior? Should I override models.SET or is there any other way around it?

Was it helpful?

Solution

Override the Image delete method to remove the Item ForeignKey

The following can be used as an intermediary model base class to add this functionality to all of your models:

from django.db import models

class Model(models.Model):
    """
    Intermediate model base class.
    """
    class Meta:
        abstract = True

    def delete(self, *args, **kwargs):
        self.clear_nullable_related()
        super(Model, self).delete(*args, **kwargs)

    def clear_nullable_related(self):
        """
        Recursively clears any nullable foreign key fields on related objects.
        Django is hard-wired for cascading deletes, which is very dangerous for
        us. This simulates ON DELETE SET NULL behavior manually.
        """
        for related in self._meta.get_all_related_objects():
            accessor = related.get_accessor_name()
            related_set = getattr(self, accessor)

            if related.field.null:
                related_set.clear()
            else:
                for related_object in related_set.all():
                    related_object.clear_nullable_related()

source

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top