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