Django模型过滤问题:如何让课时仅显示在所属对应课程中
问题描述
我在Lesson模型中设置了指向Course的外键,期望创建的课时仅能在所属的特定课程中查看,但目前出现了在课程1中创建的课时也会显示在课程2中的问题,请问该如何解决?
相关代码
views.py
def lessonpage(request): lesson = Lesson.objects.all() if request.user.is_authenticated: return render(request, "lessons/lessons.html", {'lessons': lesson}) else: return redirect('loginpage') def addlesson(request): if request.method == "POST": form = AddLessonForm(request.POST) if form.is_valid(): form.save() return render(request, "lessons/successlessons.html", {'form1': form}) form = AddLessonForm() return render(request, "lessons/addlessons.html", {'form': form}) def deletelessons(request, id): lesson = Lesson.objects.get(id=id) lesson.delete() return redirect("lessonspage")
models.py
from django.db import models class Section(models.Model): nameofsection = models.CharField(max_length=50, default="") def __str__(self): return self.nameofsection class Course(models.Model): ctitle = models.CharField(max_length=50, default="") cdescription = models.TextField(max_length=200, default="") #csection = models.ForeignKey(Section, on_delete=models.CASCADE) def __str__(self): return self.ctitle def __unicode__(self): return self.ctitle class Meta: db_table="courses" class Lesson(models.Model): title = models.CharField(max_length=50, default="") description = models.TextField(max_length=200, default="") course = models.ForeignKey(Course, on_delete=models.CASCADE, blank=True, null=True) def __str__(self): return self.title
urls.py
path('course/', coursepage, name="coursepage"), path('course/<int:pk>', CourseDetailView.as_view(), name='detailed'), path('addcourse/', addcourse, name="addcoursepage"), path('editcourse/<int:id>', updatecourse, name="editcoursepage"), path('updatecourse/<int:id>', updatecourserecord, name="updatecourse"), path('deletecourse/<int:id>', deletecourse, name="deletecourse"), path('lessons', lessonpage, name="lessonspage"), path('lessons/addlessons', addlesson, name="addlessonspage"), path('deletelessons/<int:id>', deletelessons, name="deletelessons"),
解决方案
核心问题是当前lessonpage视图直接查询所有课时(Lesson.objects.all()),未按课程过滤。按以下步骤调整即可解决:
1. 修改课时列表视图,按课程过滤
更新lessonpage,让它接收课程ID参数,只返回对应课程的课时:
def lessonpage(request, course_id): # 过滤指定课程的课时 lessons = Lesson.objects.filter(course_id=course_id) # 传递当前课程对象到模板,方便展示课程信息 course = Course.objects.get(id=course_id) if request.user.is_authenticated: return render(request, "lessons/lessons.html", {'lessons': lessons, 'course': course}) else: return redirect('loginpage')
2. 更新URL配置,传递课程ID
修改urls.py中的课时路由,增加课程ID参数:
# 替换原有lessons路由 path('lessons/<int:course_id>', lessonpage, name="lessonspage"),
3. 优化添加课时逻辑,强制关联指定课程
当前添加课时时可能未指定所属课程(course字段允许空),需调整确保课时关联到具体课程:
方式一:通过URL传递课程ID并自动绑定
修改addlesson视图,接收课程ID并自动设置关联:
def addlesson(request, course_id): course = Course.objects.get(id=course_id) if request.method == "POST": form = AddLessonForm(request.POST) if form.is_valid(): # 先创建实例不保存,再绑定课程 lesson = form.save(commit=False) lesson.course = course lesson.save() return redirect('lessonspage', course_id=course_id) return render(request, "lessons/successlessons.html", {'form1': form}) # 初始化表单时默认填充当前课程 form = AddLessonForm(initial={'course': course}) return render(request, "lessons/addlessons.html", {'form': form, 'course': course})
同步更新添加课时的URL:
path('lessons/<int:course_id>/addlessons', addlesson, name="addlessonspage"),
方式二:在表单中隐藏课程字段
如果使用ModelForm,修改AddLessonForm将course设为隐藏字段,从模板传入课程ID:
# 假设AddLessonForm是ModelForm class AddLessonForm(forms.ModelForm): class Meta: model = Lesson fields = ['title', 'description', 'course'] widgets = { 'course': forms.HiddenInput() }
然后在课程详情页的"添加课时"链接中带上课程ID:
<!-- 课程详情页模板 --> <a href="{% url 'addlessonspage' course.id %}">添加课时</a>
4. 调整课程详情页的课时入口
在CourseDetailView对应的模板中,链接到该课程的专属课时页面:
<a href="{% url 'lessonspage' course.id %}">查看该课程的课时</a>
额外优化:禁止无归属的课时
可以移除Lesson模型中course字段的blank=True, null=True,强制课时必须关联课程:
class Lesson(models.Model): title = models.CharField(max_length=50, default="") description = models.TextField(max_length=200, default="") # 去掉空值允许,确保课时必须属于某课程 course = models.ForeignKey(Course, on_delete=models.CASCADE)
内容的提问来源于stack exchange,提问作者Naig
相关产品推荐
相关产品推荐

