django中的多线程对话(如Reddit)

dot*_*tty 3 django model

我有一个应用程序,基本上是一个会话系统(很像reddit).

如果帖子可以有多个回复,回复并且有多个回复,并且对回复的回复可以有多个回复(等等)

我做了这样的模型:

class Discussion(models.Model):
    message = models.TextField()
    replies = models.ManyToManyField('self')
Run Code Online (Sandbox Code Playgroud)

和观点:

discussions = Discussions.objects.all()
Run Code Online (Sandbox Code Playgroud)

模板看起来像这样:

{% for discussion in discussions %}
    {{ discussion.message }}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

我如何建立一个系统,我可以输出这样的所有回复?

discussion
    reply
        reply
    reply
        reply
            reply
                reply
Run Code Online (Sandbox Code Playgroud)

哪个会在确保列出所有回复时尽可能降低.

Mik*_*one 5

除非回复可以是对多个帖子的回复,否则a ManyToManyField不是您想要的.你只需要一个ForeignKey:

class Discussion(models.Model):
    message = models.TextField()
    reply_to = models.ForeignKey('self', related_name='replies', 
        null=True, blank=True)
Run Code Online (Sandbox Code Playgroud)

然后你可以得到一个讨论的回复Discussion.replies.

不幸的是,没有办法在Django的模板语言中进行递归,所以你必须要么1)运行一个递归函数来获得一个"扁平化"的回复列表,并把它放在上下文中,或者2)编写一个可以执行的函数被称为递归调用,使用模板生成每个级别,如下所示:

_DiscussionTemplate = Template("""
<li>{{ discussion.message }}{% if replies %}
    <ul>
        {% for reply in replies %}
        {{ reply }}
        {% endfor %}
    </ul>
{% endif %}</li>
""".strip())

class Discussion(models.Model):
    message = models.TextField()
    reply_to = models.ForeignKey('self', related_name='replies', 
        null=True, blank=True)

    @property
    def html(self):
        return _DiscussionTemplate.render(Context({
            'discussion': self,
            'replies': [reply.html() for reply in self.replies.all()]
        }))
Run Code Online (Sandbox Code Playgroud)

然后在顶级模板中,您只需要:

<ul>
    {% for d in discussions %}
    {{ d.html }}
    {% endfor %}
</ul>
Run Code Online (Sandbox Code Playgroud)

根据需要应用CSS,使其看起来不错.

编辑:根本讨论是在Discussion.objects.filter(reply_to=None)._DiscussionTemplate包含的所有代码都包含在您的内容中models.py.这样,_DiscussionTemplate在模块加载时初始化一次.

编辑2:将HTML放在模板文件中非常简单.将设置的视图代码更改_DiscussionTemplate为:

_DiscussionTemplate = loader.get_template("discussiontemplate.html")
Run Code Online (Sandbox Code Playgroud)

然后创建discussiontemplate.html:

<li>{{ discussion.message }}{% if replies %}
    <ul>
        {% for reply in replies %}
        {{ reply }}
        {% endfor %}
    </ul>
{% endif %}</li>
Run Code Online (Sandbox Code Playgroud)

根据需要设置模板文件的路径.