如何在Django中创建关联外键的Video模型表单:默认Course并显示对应Section
如何创建满足需求的Video模型表单?
需求说明:创建Video模型的表单时,默认关联指定Course,且仅展示该Course对应的SectionVideo选项。现有模型定义如下:
现有模型代码
Course模型
class Course(models.Model): instructor = models.ForeignKey(UserProfile,on_delete=models.CASCADE) name = models.CharField(max_length = 50 , null = False,unique = True) slug = models.CharField(max_length = 50 , null = False , unique = True)
SectionVideo模型
class SectionVideo(models.Model): course = models.ForeignKey(Course , null = False , on_delete=models.CASCADE) name = models.CharField(max_length = 50 , null = False) slug = models.CharField(max_length = 50 , null = False ) serial_number = models.IntegerField(null=False)
Video模型
class Video(models.Model): section_video = models.ForeignKey(SectionVideo , null = False , on_delete = models.CASCADE) course = models.ForeignKey(Course , null = False , on_delete = models.CASCADE) title = models.CharField(max_length = 100 , null = False) video_description = models.CharField(max_length = 500 , null = True)
实现步骤
1. 编写表单类(forms.py)
通过ModelForm创建表单,重写__init__方法实现:
- 接收指定Course参数,设置为表单默认值
- 过滤
section_video选项,仅显示当前Course下的章节
from django import forms from .models import Video, SectionVideo class VideoForm(forms.ModelForm): class Meta: model = Video fields = ['section_video', 'course', 'title', 'video_description'] # 将course设为隐藏字段,避免用户修改默认关联的课程 widgets = { 'course': forms.HiddenInput(), } def __init__(self, *args, **kwargs): # 从参数中提取指定的Course course = kwargs.pop('course', None) super().__init__(*args, **kwargs) if course: # 设置course字段的初始值 self.fields['course'].initial = course # 过滤章节选项,仅展示当前课程下的SectionVideo self.fields['section_video'].queryset = SectionVideo.objects.filter(course=course) # 优化章节字段的显示标签 self.fields['section_video'].label = f"章节(所属课程:{course.name})"
2. 在视图中传递指定Course并实例化表单(views.py)
从URL参数中获取目标Course,将其传入表单初始化,处理表单的提交逻辑:
from django.shortcuts import get_object_or_404, render, redirect from .models import Course, Video from .forms import VideoForm def create_video(request, course_slug): # 通过slug获取指定课程 course = get_object_or_404(Course, slug=course_slug) if request.method == 'POST': form = VideoForm(request.POST, course=course) if form.is_valid(): form.save() # 保存后跳转至课程详情页(可根据需求修改跳转目标) return redirect('course_detail', slug=course_slug) else: # GET请求时,传入course初始化表单 form = VideoForm(course=course) return render(request, 'create_video.html', {'form': form, 'course': course})
3. 模板中渲染表单(create_video.html)
渲染表单并展示当前关联的课程信息:
<h2>为课程 {{ course.name }} 添加视频</h2> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">保存视频</button> </form>
可选优化建议
Video模型中的course字段存在冗余,因为可通过section_video.course获取关联课程。可以修改模型去掉冗余字段,简化逻辑:
class Video(models.Model): section_video = models.ForeignKey(SectionVideo, null=False, on_delete=models.CASCADE) title = models.CharField(max_length=100, null=False) video_description = models.CharField(max_length=500, null=True) # 通过属性快速获取关联课程 @property def course(self): return self.section_video.course
修改后,表单中可移除course字段,进一步简化代码。
内容的提问来源于stack exchange,提问作者md Zayed
相关产品推荐
相关产品推荐

