在Django中创建层次结构视图

时间:2017-05-05 14:50:23

标签: django hierarchy

我正在尝试在Django中创建层次结构视图,但我很难理解如何有效地使用QuerySet。

我最终的目标是显示以下课程的html页面:

Main Course 1 --- Child Course 1
              --- Child Course 2

Main Course 2 --- Child Course 3
              --- Child Course 4

每组课程都包含在div和样式等中。

在我的view.py文件中,我有以下内容:

class HierarchyView(generic.ListView):
template_name = 'curriculum/hierarchy.html'

def get_queryset(self):
    return Offering.objects.all()

def get_context_data(self, **kwargs):
    context = super(HierarchyView, self).get_context_data(**kwargs)
    context['main'] = self.get_queryset().filter(course_type='M')
    context['sub'] = self.get_queryset().filter(parent_code__in=context['main'])
    return context

设置产品模型,以便parent_code是一个自引用外键(即任何课程可以是任何其他课程的孩子),如下所示:

...
parent_code = models.ForeignKey(
    'self',
    null=True,
    blank=True,
    on_delete=models.SET_NULL)
...

在我的html模板中,我有:

{% for mainoffering in main %}
<div>
<div>{{ mainoffering.course_name }}</div>
  {% for offering in sub %}
  <div>{{ offering.course_name }}</div>
  {% endfor %}
</div>
{% endfor %}

然而,这导致所有儿童课程都出现在所有主要课程之下,无论他们是否真的是该课程的孩子,这显然不是我所追求的。

我还在学习Django的绳索,我很难找到任何用简单的英语解释我需要做什么的东西。请帮忙!

2 个答案:

答案 0 :(得分:0)

我认为您需要更改模板以将每个子课程与其父课程相匹配。也许是这样的:

{% for mainoffering in main %}
<div>
<div>{{ mainoffering.course_name }}</div>
  {% for offering in sub %}
    {% if offering.parent_code == mainoffering %}
        <div>{{ offering.course_name }}</div>
    {% endif %}
  {% endfor %}
</div>
{% endfor %}

答案 1 :(得分:0)

上下文[&#39; sub&#39;]将返回所有内容,不进行任何分组,排序等。您可以执行以下操作以获得所需的行为。

您可以执行相关的预取。

from django.db.models import Prefetch

offerings = Offering.objects.filter(course_type='M').prefetch_related(
     Prefetch(
         "courses_subset",
         queryset=Offering.objects.filter(parent_code__in=offerings),
         to_attr="sub"
    )
)
for o in offerings:        
    print o.sub

你实际上可以在模型中创建一个方法并创建一个模板标签(我很可能会使用它)。

method in your Offering model

def get_child_courses(self):
    child_courses = Offerings.objects.filter(parent_code=self.id)
    return child_courses

template tag

@register.simple_tag
def get_child_courses(course):
    return course.get_child_courses()

在你的模板中:

{% for mainoffering in main %}
<div>
<div>{{ mainoffering.course_name }}</div>
  {% for offering in mainoffering|get_child_course %}
  <div>{{ offering.course_name }}</div>
  {% endfor %}
</div>
{% endfor %}

您可以按照accraze的建议将它们分组到模板中。我个人会选择第二个选项