Reputation: 2146
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?
Upvotes: 8
Views: 1847
Reputation: 18202
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()
Upvotes: 1