模板问题中的Django递归关系嵌套

时间:2019-05-26 20:30:32

标签: django python-3.x django-models django-templates django-views

首先,我想对所有人在堆栈溢出中表示感谢。我研究了 能够找到我在Django中的递归关系问题的许多答案;所有 从模型创建,视图到现在的模板。我是Python的新手,因此, Django的新手。因此,我感谢您提供了详细的示例来回答其他人提出的问题。

tl; dr

我需要一个嵌套(有序)列表,该列表与另一个模型具有外键关系。我尝试使用递归外键“自我”,但无法完成我的研究任务。感谢@somecallitblues(有人可以告诉我如何给他信誉吗?)指出Django-mptt,我得以解决此问题。

(我不知道是否或如何将此问题标记为已回答和/或是否应该更改标题,以便其他人也可以找到相同的问题。我可以在格式化问题时使用一些帮助(s)/或正确的提问方式。任何指点都会有所帮助。)

模型

    from mptt.models import TreeForeignKey, MPTTModel

    class Topic(models.Model):
        wherein = models.CharField()            
        partof = models.CharField()            
        title = models.CharField()            
        slug = models.SlugField()

    class TextNode(MPTTModel):
        topic = models.ForeignKey(Topic)
        parent = TreeForeignKey(
                "self",
                on_delete=models.CASCADE,
                related_name="children",
                related_query_name="child",
                null=True,
                blank=True,
            )    
        body = models.TextField()

查看

    def topic_node_list(request, slug):
        topics = Topic.objects.filter(slug__exact=slug)
        textnodes = TextNode.objects.filter(topic__slug__exact=slug)

        return render(request, "node_test.html", {"topics": topics, "textnodes": textnodes})    

模板

{% load mptt_tags %}

<ul>
    {% for topic in topics %}
        <h2>{{ topic.title }}</h2>
        <ul>
        {% recursetree textnodes %}
            <li>
              {{ node.body}}
            {% if not node.is_leaf_node %}
                <ul class="children">
                    {{ children }}
                </ul>
            {% endif %}
            </li>
        {% endrecursetree %}
        </ul>
    {% endfor %}
</ul>

urls.py

urlpatterns = [
    path("nodes/<slug:slug>/", views.topic_node_list, name="nodes"),    
    path("", views.home, name="home"),
    path('admin/', admin.site.urls),
 ]

一切正常!因此,再次感谢您@somecallitblues!

但是!我想将

更改为有序列表,然后根据嵌套级别更改类型。我希望第一个有序列表是1.,2.,3,下一个是a。,b。,c。,然后是i。,ii。 iii。等等。可以通过JavaScript或jQuery完成吗?我什至不知道在搜索引擎中要查找的位置或要搜索的内容。

这是我第一次使用Python进行项目。我从12月份才开始学习,我被束缚在编写简单的博客的过程中,需要挑战,男孩,男孩,我学到了很多东西!我正从重病中恢复过来,已经退役了近十年,所以要回到困境中一直是个挑战。 Python极大地帮助了我恢复肌肉记忆。

结束tl; dr

我正在尝试创建一个“报告”(由于缺乏更好的术语)应用程序。它有一个目录,简介, 但是,您想要许多部分,参考书目,脚注,索引,词汇表等。我也有一个应用程序 对于可以问到的问题以及回答上述问题的能力,这就是我正在 问题以及我提出问题的依据。我的模型,视图和模板代码将在下面添加。 (如果我能弄清楚如何发布代码)。

我有一个主题模型和一个身体模型。主题模型就是问题的主题。 正文模型是问题文本的存储位置。每个问题可能有也可能没有 子问题。主体模型具有主题模型的外键。身体模型具有递归 “自我”的外键。尽管我确实有一个“我该怎么办”的问题,但这种关系仍然很好 我将在下面列出。 **

对于视图,我具有Subject模型的通用ListView,并为Body模型添加了额外的上下文。

模板是我的问题的基础。我可以嵌套“主题”的有序列表,并且 问题的“主体”。 正好。在这里发布问题(或子问题)的子项。

模板将在子列表中按顺序列出父问题。然后孩子们 开始作为父问题列出,因此本质上它们被发布了两次。一旦正确地作为子问题, 然后错误地作为父问题(尽管我想知道如何将子问题列为 子问题的父级(孙子关系?)

我曾经考虑过同时使用自定义模型管理器或类方法来从 孩子们,但是我该怎么做呢?如我所说,我是python和Django的新手,所以我还没有 线索。

我正在使用: Django版本:2.1.8 Django-pyodbc-azure 2.1 python 3.7.2

这是我的代码:

模型

class Subject(models.Model):
    ...
        wherein = models.CharField(
                max_length=3,
                choices=WHERE,
                default=SECTION,
                help_text="Where in the report",
                )
        partof = models.CharField(
                max_length=5,
                choices=PART_OF,
                default=QUESTION,
                help_text="Is this a question or answer?")
        title = models.CharField(
                max_length=80,
                help_text="What is the subject of the question",
                )
        slug = models.SlugField(
                max_length=80,
                help_text="This is what the url will be"
                )
    class Body(models.Model):
        subject = models.ForeignKey(
                Subject,
                on_delete=models.CASCADE,
                verbose_name="subject of",
                help_text="What subject does this text relate to?"
                )
        parent = models.ForeignKey(
                "self",
                on_delete=models.CASCADE,
                verbose_name="subsection of",
                related_name="subsections",
                related_query_name="subsection",
                null=True,
                blank=True,
                )
        text = models.TextField(
                max_length=1500,
                help_text="Text of the paragraph",)

查看

    class QuestionList(ListView):
        queryset = Subject.objects.filter(id=2)
        template_name = "questions/questions_list.html"
        context_object_name = "subjects"

        def get_context_data(self, *args, object_list=None, **kwargs):
            context = super(QuestionDetail, self).get_context_data(**kwargs)
            context["bodies"] = Body.objects.filter(subject__partof__exact="QUES")
            return context

模板

    <ol type="1">
        {% for subject in subjects %}
                <li><b>{{ subject.title }}</b></li>
    <ol type="a">
        {% for body in bodies %} # I believe this is where I need to filter for just parents
            <li>{{ body.text }}</li>
            <ol type="i">
                {% for sub in body.subsections.all %}
                    <li>{{ sub.text }}</li>
                {% endfor %}
            </ol>
        {% endfor %}
    </ol>
    </ol>
    {% endfor %}

我想选择进一步嵌套(有父母的孩子的孩子)。

我应该为父母添加额外的背景信息吗: Body.objects.filter(parent_id__isnull=True)? 如果是这样,在模板中如何处理带有孩子的关系? (嵌套列表)。

**附带问题:我如何将“孩子”作为自己“孩子”的父母? 以及如何将它们嵌套在模板中?

我希望我已经适当地安排了我的问题,我尝试了尽可能多的张贴,我希望这很容易 解决方法。如果有什么我想念的,请随时提问!

谢谢!

更新: 这是要呈现为html的模板

# The first ol

    <li>1. This would be the topic a question</li>
           <li>a. This would be the parent question.</li>
                 <li>i. This would be the child of the parent question a.</li>
                 <li> ii. This would also be a child of the parent question a.</li>
           <li>b. This would be the second parent question</li>
           <li>c. This would be the third parent question</li>
                  <li>i. This would be the child of the parent question c.</li>
                  <li> ii. This would also be a child of the parent question c.</li>
           <li>d. … and so on</li>
    <li>2. This would be the next topic of a question</li>

更新2 : 我意识到我现在没有更新事物的渲染方式。在这里:

    <li>1. This would be the topic a question</li>
           <li>a. This would be the parent question.</li>
                 <li>i. This would be the child of the parent question a.</li>
                 <li> ii. This would also be a child of the parent question a.</li>
           <li>b. This would be the second parent question</li>
           <li>c. This would be the third parent question</li>
                  <li>i. This would be the child of the parent question c.</li>
                  <li> ii. This would also be a child of the parent question c.</li>
           <li>d. … and so on</li>
           <li>e. This would be the child of the parent question a.</li>
           <li>f. This would also be a child of the parent question a.</li>           
           <li>g. This would be the child of the parent question c.</li>
           <li>h. This would also be a child of the parent question c.</li>
           <li>i. … and so on</li>
    <li>2. This would be the next topic of a question</li>

我目前正在阅读有关添加自定义模型管理器的Django文档。有点困惑,但是我会坚持尝试新的做事方式。就像我说的那样,我在这个时候有点迷失了,真的可以使用一些帮助。

更新3

我接受了@somecallitblues的建议,并花了一些时间浏览Django-treebead和Django-mptt。使用Treebeard,我无法弄清楚如何使用模板。使用mppt,我可以构建模型,但是无法将两个模型连接在一起以在模板中显示,并且视图必须硬编码topic_id。我觉得我想念什么。谁能指出我的问题所在?我正在阅读所有文档,但不了解在哪里以及如何应用这些方法。我是Web开发的新手,同时还是python的新手。

我将发布我现在的内容,如果有人可以给我一些有关我应该研究的内容的指示,我将不胜感激。

对于模型,主题仍然相同,只是命名为Topic,所以我不会重新发布它:

更新的人体模型:

class BodyNode(MPTTModel):
    topic = models.ForeignKey(
            Topic,
            on_delete=models.CASCADE,
            verbose_name="Of topic",
            help_text="What topic is being discussed?",
            )    
    text = models.TextField(
            max_length=750,
            help_text="Content of the paragraph",
            )
    parent = TreeForeignKey(
            "self",
            on_delete=models.CASCADE,
            related_name="children",
            blank=True,
            null=True,
            )

查看:

def topic_list(request):
    bodynodes = BodyNode.objects.filter(topic_id=2)

    return render(request, "mpttapp/topic_list.html", {"bodynodes": bodynodes})

模板:

 <ol class="root" type="a">
                    {% recursetree bodynodes %}
                        <li>
                            {{ node.text }}
                            {% if not node.is_leaf_node %}
                                    <ol type="i" class="children">
                                    {{ children }}
                                    </ol>
                            {% endif %}
                        </li>
                    {% endrecursetree %}
                </ol>

现在,列表按原样显示,但仅适用于topid_id = 2。我需要使它动态化,并能够为url添加slug字段,以及能够使用来自的标题字段主题模型,所以我已经走了一半。

我确实要感谢@somecallitblues的帮助,我觉得使用mptt是可行的方法,因为如果需要的话,我将能够进行更深入的嵌套。我只是觉得自己有些烦恼,但是我真的下定决心要解决这个问题。我只需要一些指针即可。

更新4

我想我已经解决了恋爱问题。我将使主题模型成为带有BodyNode中的TreeForeignKey的MPTTModel。我认为与Topic模型的关系是我遇到的嵌套问题。由于该应用程序本身就是一个“树/目录对象”的“排序”,所以这可能是我挣扎的原因。如果可行,我将在明天再次进行更新,我真的很想解决此问题,并使本主题对遇到相同问题的其他人有所帮助。

我确实花了很多时间阅读Django项目站点上的文档,但是在构建模板/视图时我还是有些困惑。如果有人知道一个不错的教程网站或一本除了建立一个简单的博客以外还能做的更好的书,我将不胜感激。

0 个答案:

没有答案