在Django中创建无限论坛层次结构 [英] Creating an unlimited forum hierarchy in Django

查看:108
本文介绍了在Django中创建无限论坛层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



到目前为止,我有:


  class Forum(models.Model):
name = models.CharField(max_length = 255)
slug = models .SlugField(max_length = 150)
description = models.TextField()

def __unicode __(self):
return self.name

class SubForum (models.Model):
parent_forum = models.ForeignKey('Forum',related_name ='forums')
parent = models.ForeignKey('self',blank = True,null = True,related_name = 'children')
name = models.CharField(max_length = 300)
slug = models.SlugField(max_length = 150)
description = models.TextField()

def __unicode __(self):
if self.parent:
return u'%s:%s - %s'%(self.parent_forum.name,
self.parent.name,
self.name)
return u'%s:%s'%(self.parent_forum.name,self.name)


这个功能大部分是因为我可以选择一个父类,尽管我不知道如何选择一个孩子的父母的父母。例如,如果我有以下内容:

 祖父母 - >父母 - >孩子

如何从孩子中选择祖父母?



这种层次结构也使得Django管理员相当凌乱,因为它并没有以有序的方式级联。我必须从头开始构建整个管理员,以便将其组织成可用的界面?



最后, __ unicode __ 在SubForum模型中的功能允许我打印父母,但是祖父母呢。我可以得到 __ unicode __ 打印所有祖先?



谢谢。

解决方案

使用父/子关系



尽管您可以使用两个型号,儿童关系表示您的论坛层次结构,由于模型存储在关系型SQL数据库中,您必须首先考虑如何使用这些模型,以便您可以对其进行适当的建模。



如果您只需要执行宽度优先搜索(BFS),即只选择单个论坛的直接父母或孩子,像您写的代码,Django ORM将会很棒。



你甚至可以得到孩子的祖父母,但它需要大量的SQL SELECT JOIN 操作一旦ORM命中数据库,这可能会很慢。



使用单个模型



所以当你的模型好的时候,它不是真的适合你的要求,更具体地说,从随机节点(孩子的祖父母)开始,从层次开始向上/向下选择节点



你想要做的是构建一个简单的N-ary树数据结构,或换句话说,一个层次结构和遍历它。你真的不需要两个模型,只有一个与自己的关系的模型就足够了(例如,我已经称它为 Node )。要在这个模型中获得第N个父母,你只需要在每次关系之后循环n次(这基本上是一个 linked-list

  n = 2#祖父母
node = Model.objects.get (pk = 1)
而n:
如果node.parent:
node = node.parent
#在循环结束`node`指向祖父母



SQL数据库建模树结构



有可能在SQL数据库中实现树的方式,但在您的情况下,我建议使用 MPTT ,我们可以说邻接列表模型来构建它。两者都是易于操作和存储这种结构的技术。 MPTT 将需要对数据库进行更多写入才能添加/移动树上的节点,但是选择具有随机根(子)的部分树是非常容易的,因为您只需要在两个整数字段上进行过滤。



使用邻接列表,您可以用较少的写入来更新树,但是您需要做更多的操作来选择部分树从随机根开始。



关于MPTT作为Django应用程序的实现,请尝试 django-mptt



杂项:好的文章分层数据数据库设计。


I'm trying to design models for a forum I wish to create in Django.

So far I have:

class Forum(models.Model):
    name = models.CharField(max_length=255)
    slug = models.SlugField(max_length=150)
    description = models.TextField()

    def __unicode__(self):
        return self.name

class SubForum(models.Model):
    parent_forum = models.ForeignKey('Forum', related_name='forums')
    parent = models.ForeignKey('self', blank=True, null=True, related_name='children')
    name = models.CharField(max_length=300)
    slug = models.SlugField(max_length=150)
    description = models.TextField()

    def __unicode__(self):
        if self.parent:
            return u'%s: %s - %s' % (self.parent_forum.name,
                                     self.parent.name,
                                     self.name)
        return u'%s: %s' % (self.parent_forum.name, self.name)

This works for the most part as I am able to choose a parent category although I am not sure how to select parent of a child's parent. For example if I had the following:

Grandparent -> Parent -> Child

How would I select Grandparent from Child?

This kind of hierarchy also makes the Django admin rather messy as it doesn't cascade in an orderly fashion. Do I have to build the entire admin from scratch in order to organise this into a usable interface?

Lastly the __unicode__ function in the SubForum model allows me to print the parent but what about a grandparent. Can I get __unicode__ to print all ancestors?

Thanks.

解决方案

Using parent/child relationship

While it is true that you could use two models with parent/child relationship to represent you forum hierarchy, due to the fact that the models are stored in relational SQL database you have to think first how you are going to use those models so you can in turn properly model them.

If you will only every need to do breadth-first search (BFS), that is select only immediate parents or children of a single forum, code like you wrote it and Django ORM will be great.

You could even get the grandparent of the child but it will require a lot of SQL SELECT and JOIN operations once the ORM hits the database, which could potentially be rather slow.

Using a single model

So while your model is ok, it's not really suitable for your requirements, or more specifically selecting nodes far up/down the hierarchy starting with the random node (grandparents of a child).

What you want to do is to build a simple N-ary tree data structure, or in other words, a hierarchy and traverse it. You don't really need two models for this, only one models with relationship to itself would suffice (I've called it Node for example). To get a N-th parent in this model you would simply loop n times each time following your relationship (this is basically a linked-list)

n = 2 # Grandparent
node = Model.objects.get(pk=1)
while n: 
   if node.parent:
      node = node.parent
# At the end of the loop `node` points to the grandparent

Modeling tree structure in SQL database

There are potentially number of ways to implement trees in a SQL database but in your case I would suggest using MPTT, over lets say adjacency list model to build it. Both are techniques for easy manipulation and storage of such structures. MPTT will require more writes to the database in order to add/move nodes around the tree but to select partial tree with random root (child) is super easy since you only need to filter on two integer fields.

With adjacency lists you could potentially update the tree with fewer writes, but you would need to do much more operations to select partial tree starting from random root.

As for implementation of MPTT as a Django application try django-mptt.

Misc: nice article hierarchical data database design.

这篇关于在Django中创建无限论坛层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆