You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CourseDetailView中展示关联的Module实例?

Django 关联模型数据展示问题解决

问题背景

我通过外键关联了Course、Module、Report三个模型,想要在CourseDetailView(DetailView)中展示当前课程对应的所有Module实例,以及每个Module关联的Report实例。但目前用Module.objects.all()会取出所有模块,无法过滤出当前课程对应的部分,不知道该如何处理。

模型定义

class Course(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title = models.CharField(max_length=200, blank=True, null=True)
class Module(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title = models.CharField(max_length=200, blank=True, null=True)
    course_id = models.ForeignKey(
        Course,
        null=True,
        on_delete=models.SET_NULL,
        related_name="modules",
        default=uuid.uuid4,
    )
class Report(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title = models.CharField(max_length=200, blank=True, null=True)
    module_id = models.ForeignKey(
        Module,
        null=True,
        on_delete=models.SET_NULL,
        related_name="reports",
        default=uuid.uuid4,
    )

当前视图代码

class CourseDetailView(DetailView):
    model = Course
    context_object_name = "course"
    template_name = "course/course_detail.html"
    fields = ["title", "description"]

    def get_context_data(self, **kwargs):
        context = super(CourseDetailView, self).get_context_data(**kwargs)
        context["courses"] = Course.objects.filter(pk=self.kwargs.get("pk"))
        return context

当前模板代码

{{ course.description|safe }}

{% for module in modules %}
<div>
    <h2><a href="{{ module.get_absolute_url }}">{{ modules.title }}</a></h2>
</div>
{% endfor %}

解决方案

1. 获取当前课程关联的Module

DetailView会自动将当前请求的Course实例赋值给self.object,结合Module外键设置的related_name="modules",可以直接通过实例关联获取对应模块:
修改get_context_data方法:

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    # 直接通过当前Course实例获取关联的所有Module
    context["modules"] = self.object.modules.all()
    return context

如果不想依赖related_name,也可以手动过滤:

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context["modules"] = Module.objects.filter(course_id=self.object)
    return context

2. 修正模板错误

模板中循环变量是module,但你写了{{ modules.title }},这会导致无法正确显示模块标题,需要改为:

{{ course.description|safe }}

{% for module in modules %}
<div>
    <h2><a href="{{ module.get_absolute_url }}">{{ module.title }}</a></h2>
    <!-- 额外:展示当前模块关联的Report -->
    {% for report in module.reports.all %}
    <p>{{ report.title }}</p>
    {% endfor %}
</div>
{% endfor %}

3. 性能优化(可选)

为避免页面渲染时出现N+1查询问题,可以预加载关联数据,在视图中添加get_queryset方法:

def get_queryset(self):
    # 预加载当前课程的所有Module,以及每个Module的Report
    return Course.objects.prefetch_related('modules__reports').filter(pk=self.kwargs.get("pk"))

内容的提问来源于stack exchange,提问作者BlindSide

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 22:10:10