在django模型中加载树结构的麻烦

时间:2013-08-26 12:47:32

标签: python django django-models

我有2个像这样的django模型

class Thread(models.Model):

    title = models.CharField(max_length=255, blank=True)

class Post(models.Model):

    message = models.TextField(blank=True)
    thread = models.ForeignKey(Thread, related_name='posts')
    depth = models.PositiveIntegerField(default=0)
    reply_to = models.ForeignKey('self', null=True, related_name='replies',
            blank=True)

当我这样做时,我注意到了

roots = Thread.posts.filter(depth=0)
for post in roots:
   replies = post.replies

django执行查询以获取所有根,然后执行新查询以获取特定帖子的子项,我知道我将使用特定线程中的所有帖子。

我想知道是否有办法让django使用一个查询加载所有帖子,我也可以使用模型的关系来递归地获取所有子项。

2 个答案:

答案 0 :(得分:1)

它不是内置于django,但你可以使用像treebeard或django-mptt这样的应用程序。

https://tabo.pe/projects/django-treebeard/

https://github.com/django-mptt/django-mptt

答案 1 :(得分:0)

如果您只想获得与特定主题相关的所有帖子,那么您可以执行以下操作:

posts = Post.objects.filter(thread=thethread)

其中'thethread'是你感兴趣的Thread对象。在reply_to和depth上对它进行排序也很有用,这样它就会以一个容易以正确的顺序走树的顺序返回:

posts = Post.objects.filter(thread=thethread).order_by('reply_to', 'depth')

tuxacanfly建议使用django-treebeard和django-mptt对于在SQL中使用分层数据时减少数据库查询非常有用,如果您需要更多的灵活性,那么只需返回特定线程的所有帖子,这将是很好的选择。

从数据结构看,您正在为论坛或评论系统执行此操作 - 关于此的一篇好文章是http://www.sqlteam.com/article/sql-for-threaded-discussion-forums,它在https://github.com/danirus/django-comments-xtd处有一个django实现