Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I stop this cascading delete from happening in Django?

I have three model classes in a Django app:

class Folder(models.Model):
  ...
  folder = models.ForeignKey('Folder',null=True,blank=True,related_name='folders')
  front_thumbnail_image = models.ForeignKey('Image',verbose_name='Front Thumbnail',null=True,blank=True,related_name='front_thumbnail_for_folders')
  middle_thumbnail_image = models.ForeignKey('Image',verbose_name='Middle Thumbnail',null=True,blank=True,related_name='middle_thumbnail_for_folders')
  back_thumbnail_image = models.ForeignKey('Image',verbose_name='Back Thumbnail',null=True,blank=True,related_name='back_thumbnail_for_folders')

class Image(models.Model):
  ...
  folder = models.ForeignKey(Folder,related_name='images',null=True)

class ImageRepresentation(models.Model):
  ...
  image = models.ForeignKey(Image, related_name="image_representations")

Given this model, when I delete an Image in the admin site, I would expect the ImageRepresentations associated with that Image to be deleted as well, and the Folder enclosing that Image to be left alone.

The admin site tells me that the enclosing Folder will be deleted as well. What can I do to get the desired behavior? I looked into delete cascade rules, but nothing I tried seemed to work.

Edited to add three foreign keys on Folder (the thumbnail image ones)... I totally overlooked those (obviously). There are no other relationships, honest.

like image 679
Hilton Campbell Avatar asked Dec 06 '12 16:12

Hilton Campbell


People also ask

What is on delete cascade Django?

CASCADE. Cascade emulates the SQL constraint of ON DELETE CASCADE. Whenever the referenced object (post) is deleted, the objects referencing it (comments) are deleted as well.

What is Cascade in Django?

CASCADE: will remove the child object when the foreign object is deleted. SET_NULL: will set the child object foreign key to null. SET_DEFAULT: will set the child object to the default data given while creating the model.

Does Django save call clean?

save() calls the clean. This way the integrity is enforced both from forms and from other calling code, the command line, and tests. Without this, there is (AFAICT) no way to write a test that ensures that a model has a FK relation to a specifically chosen (not default) other model.

What is On_delete Cascade?

Use the ON DELETE CASCADE option to specify whether you want rows deleted in a child table when corresponding rows are deleted in the parent table. If you do not specify cascading deletes, the default behavior of the database server prevents you from deleting data in a table if other tables reference it.


1 Answers

As Thomas has said, the default on_delete behaviour of a ForeignKey is models.CASCADE. Implying the 'child' model will be deleted when the 'parent' model is deleted.

A simple solution would be to include on_delete=models.SET_NULL to each of the ForeignKey to Image fields of the Folder model like so:

front_thumbnail_image  = models.ForeignKey('Image',on_delete=models.SET_NULL, null=True, ...)
middle_thumbnail_image = models.ForeignKey('Image',on_delete=models.SET_NULL, null=True, ...)
back_thumbnail_image   = models.ForeignKey('Image',on_delete=models.SET_NULL, null=True, ...)
like image 159
Stefan Collier Avatar answered Nov 10 '22 03:11

Stefan Collier