Alf*_*ang 6 python django model-view-controller orm model
我在Django(1.8.5)中定义了以下模型:
class PubishInfo(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)
Run Code Online (Sandbox Code Playgroud)
其中图书和NewsPaper
股票相同型号PublishInfo
的OneToOneField
,这实际上是一种独特的外键.
现在,如果我删除一个PublishInfo
Object,则使用级联删除相关Book
或Newspaper
对象.
但事实上,我想要删除的PublishInfo
对象级联当我删除Book
或Newspaper
对象.这种方式是我打电话的方式.
在这种情况下,有没有什么好方法可以自动级联删除反向?
您将post_delete
信号附加到模型,以便在删除Book
或的实例时调用它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()
Run Code Online (Sandbox Code Playgroud)
save
和delete
方法的另一个直接解决方案:与@ozgur 的答案相比,我发现使用信号级联删除操作与通过覆盖Model.delete()
方法删除的效果相同,而且我们可能会自动创建附加的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()
Run Code Online (Sandbox Code Playgroud)
因此,很快我意识到三个列表字段和方法在将PublishInfo
模型附加为字段的每个模型上显然是多余的。
那么,我们为什么不使用继承呢?
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
Run Code Online (Sandbox Code Playgroud)
记得添加abstract = True
它的元类。
所以,现在我们可以自由地添加PublishInfo
我们想要附加到该模型的任何其他模型,并且我们可以制作多个这样的抽象模型:
class Book(PublishInfoAttachedModel,
models.Model):
pass
class NewsPaper(PublishInfoAttachedModel,
CommentsAttachedModel, # if we have other attached model info
models.Model):
pass
Run Code Online (Sandbox Code Playgroud)
注意models.Model
后面的超类列表中的类可以忽略,我写这只是为了使类更明显地作为Model
.