Django模型 - 具有自我关系的抽象类

时间:2017-10-02 20:31:53

标签: python django inheritance database-design data-modeling

我试图在Django中设计论坛帖子。用户可以发布线程,回复线程或回复其他线程回复(如Reddit评论中)。所有帖子都分享了日期和作者等基本信息,所以我想我要做一个抽象的Post课程。由于所有帖子都有一个他们回复的parent帖子,我的直觉是尝试在抽象类上定义它:

class Post(models.Model):
    content = models.TextField(max_length=1000)
    parent = models.ForeignKey('self', null=True)
    createdBy = models.ForeignKey(User)
    class Meta:
        abstract = True

class Thread(Post):
    title = models.CharField(max_length=200)

class ThreadReply(Post):
    score = models.IntegerField(default=0)

但结果是子类只能拥有相同类型的父类,而ThreadReply实际上应该能够拥有一个父类Thread或父级是一个父类。 ThreadReply。 一种解决方案是如果我在ThreadReply中定义两种关系:

class Post(models.Model):
    content = models.TextField(max_length=1000)
    createdBy = models.ForeignKey(User)
    class Meta:
        abstract = True

class Thread(Post):
    title = models.CharField(max_length=200)

class ThreadReply(Post):
    score = models.IntegerField(default=0)
    parentThread = models.ForeignKey(Thread,null=True)
    parentReply = models.ForeignKey(ThreadReply,null=True)

但那并不觉得......面向对象足够吗?令我困扰的是,每个ThreadReply对象都会有一个浪费的关系,因为从功能上来说,它只能是对ThreadThreadReply的回复。

1 个答案:

答案 0 :(得分:0)

感谢达伦斯的评论,我调查了Generic Relations并找到了我需要的东西。它确实涉及更改继承,使父类不再是抽象的:

from django.contrib.contenttypes.fields import GenericForeignKey,GenericRelation
from django.contrib.contenttypes.models import ContentType

class Post(models.Model):
    content = models.TextField(max_length=1000)
    createdBy = models.ForeignKey(User)
    score = models.IntegerField(default=0)
    content_type = models.ForeignKey(ContentType,on_delete=models.CASCADE,null=True)
    object_id = models.PositiveIntegerField(null=True)
    parent = GenericForeignKey(content_type,object_id)
    replies = GenericRelation('Post')

class Thread(Post):
    title = models.CharField(max_length=200)

Now Post用于线程回复,线程本身只是扩展它。邮政有一个多态的父母'可以接受ThreadPost的关系。