I have the below models defined in Django(1.8.5):
class PublishInfo(models.Model):
pass
class Book(models.Model):
info = models.OneToOneField(
PublishInfo, on_delete=models.CASCADE)
class Newspaper(models.Model):
info = models.OneToOneField(
PublishInfo, on_delete=models.CASCADE)
Where Book and NewsPaper shares a same model PublishInfo as a OneToOneField, which is in fact a unique foreign key.
Now, if I delete a PublishInfo Object, the relating Book or Newspaper object is deleted with cascading.
But in fact, I want to delete the PublishInfo object cascading when I delete the Book or Newspaper object. This way is the way I may call.
Is there any good way to automatically cascading the deletion in the reverse direction in this case? And, if yes, could it be explained?
CASCASE. When we set the on_delete parameter as CASCADE, deleting the reference object will also delete the referred object. This option is most useful in many relationships. Suppose a post has comments; when the Post is deleted, all the comments on that Post will automatically delete.
To delete a record we do not need a new template, but we need to make some changes to the members template. Of course, you can chose how you want to add a delete button, but in this example, we will add a "delete" link for each record in a new table column. The "delete" link will also contain the ID of each record.
All the model objects or instances in Django have a delete() method, which can be used to delete that record. Now, this delete() method can be also be used to delete a single record and a bunch of them.
You attach post_delete signal to your model so it is called upon deletion of an instance of Book or Newspaper:
from django.db.models.signals import post_delete
from django.dispatch import receiver
@receiver(post_delete, sender=Book)
def auto_delete_publish_info_with_book(sender, instance, **kwargs):
instance.info.delete()
@receiver(post_delete, sender=Newspaper)
def auto_delete_publish_info_with_newpaper(sender, instance, **kwargs):
instance.info.delete()
save and delete method:Comparing to the answer of @ozgur, I found using signal to cascading the delete action has the same effect as deleting by overriding the Model.delete() method, and also we might auto create the attached PublishInfo:
class Book(models.Model):
info = models.OneToOneField(
PublishInfo, on_delete=models.CASCADE)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
if not self.info:
self.info = Publish.objects.create()
super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
super().delete(*args, **kwargs)
if self.info:
self.info.delete()
So, soon I realized the three listing field and methods are obviously redundant on each Model which was attaching the PublishInfo models as a field.
So, why don't we use inheritance?
class PublishInfoAttachedModel(models.Model):
info = models.OneToOneField(
PublishInfo, related_name='$(class)s',
on_delete=models.CASCADE)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
if not self.info:
self.info = Publish.objects.create()
super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
super().delete(*args, **kwargs)
if self.info:
self.info.delete()
class Meta:
abstract = True
Remember to add abstract = True in its meta class.
So, now we are free to add PublishInfo in any other models we want to attach that model, and we can make more than one such abstract models:
class Book(PublishInfoAttachedModel,
models.Model):
pass
class NewsPaper(PublishInfoAttachedModel,
CommentsAttachedModel, # if we have other attached model info
models.Model):
pass
Notice the models.Model class in the trailing super class list can be ignored, I wrote this is just to make the classes more obvious as a Model.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With