在 Django 中创建层次结构视图
Creating a Hierarchy View in Django
我正在尝试在 Django 中创建层次结构视图,但我很难理解如何有效地使用 QuerySets。
我最终的目标是 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
Offering 模型的设置使得 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 的诀窍,我正在努力寻找任何可以用简单的英语解释我需要做什么的东西。请帮忙!
我认为您需要更改模板以使每个子课程与其父课程相匹配。可能是这样的:
{% 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 %}
上下文['sub']将return所有这些,没有任何分组、排序等。您可以做几件事来获得所需的行为。
你可以做一个预取相关的。
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 %}
您可以按照 acraze 的建议将它们分组到您的模板中。我个人会选择第二个选项
我正在尝试在 Django 中创建层次结构视图,但我很难理解如何有效地使用 QuerySets。
我最终的目标是 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
Offering 模型的设置使得 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 的诀窍,我正在努力寻找任何可以用简单的英语解释我需要做什么的东西。请帮忙!
我认为您需要更改模板以使每个子课程与其父课程相匹配。可能是这样的:
{% 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 %}
上下文['sub']将return所有这些,没有任何分组、排序等。您可以做几件事来获得所需的行为。
你可以做一个预取相关的。
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 %}
您可以按照 acraze 的建议将它们分组到您的模板中。我个人会选择第二个选项