Django ModelForm无法正确获取RoutinePlans字段问题求助
问题分析与解决方案
看起来你遇到的核心问题并不是表单引用了错误的模型字段,而是在保存RoutinePlans对象时,没有将当前编辑的Routines实例关联到新创建的计划条目上。你的PlanForm确实是基于RoutinePlans模型的,只是因为缺少外键关联导致保存失败,让你误以为字段引用出了问题。
下面是具体的修复步骤:
1. 修复editplan视图的POST处理逻辑
在提交表单后,你需要先获取当前编辑的Routines实例,再把它赋值给RoutinePlans对象的routine外键字段。修改后的视图代码如下:
def editplan(request, routine_id): # 提前获取当前要编辑的routine实例,避免重复查询 current_routine = Routines.objects.get(id=routine_id) routine_name = current_routine.name if request.method == 'POST': form = forms.PlanForm(data=request.POST) if form.is_valid(): obj = form.save(commit=False) # 关键:将当前routine实例关联到新的计划条目 obj.routine = current_routine obj.save() return redirect('fitnessmanagement:editplan', routine_id=routine_id) else: # 打印表单错误方便调试 print(form.errors) else: # GET请求时初始化表单 form = forms.PlanForm() # 以下是你的页面变量查询逻辑,保持不变 plan = RoutinePlans.objects.filter(routine_id=routine_id) plan_weeks = RoutinePlans.objects.filter(routine_id=routine_id).values('week').distinct() plan_dayss = RoutinePlans.objects.filter(routine_id=routine_id).values('day', 'week').distinct() plan_excercise_name = RoutinePlans.objects.filter(routine_id=routine_id).values('day', 'week', 'exercise_id', 'set_type_id').distinct() plan_excercise = RoutinePlans.objects.filter(routine_id=routine_id).prefetch_related('exercise') names = WeightExercises.objects.all() setDetails = RoutinePlans.objects.filter(routine_id=routine_id).values('set', 'reps', 'day', 'week', 'exercise', 'set_type') set_type = SetType.objects.all() variables = { 'form': form, 'id': routine_id, 'routine_name': routine_name, 'plan': plan, 'plan_weeks': plan_weeks, 'plan_exercises': plan_excercise, 'plan_exercise_name': plan_excercise_name, 'plan_days': plan_dayss, 'setDetails': setDetails, 'names': names, 'set_type': set_type, } return render(request, template_name='editplan.html', context=variables)
2. 调试小技巧
如果表单仍然无法正常保存,在form.is_valid()为False的分支里打印form.errors,可以看到具体的验证错误信息(比如必填字段缺失、外键关联错误等),这有助于快速定位问题。
3. 优化表单的day字段(可选)
你手动定义的DAY_CHOICES可以简化为更简洁的写法,避免手动输入出错:
class PlanForm(forms.ModelForm): DAY_CHOICES = [(str(i), str(i)) for i in range(1, 8)] day = forms.ChoiceField(widget=forms.Select, choices=DAY_CHOICES) class Meta: model = RoutinePlans exclude = ['routine']
4. 模板渲染检查
确保你的模板里所有表单字段都正确对应RoutinePlans的字段,比如{{ form.week }}、{{ form.exercise }}等,这些都是PlanForm基于RoutinePlans生成的字段,并没有引用Routines的字段。
内容的提问来源于stack exchange,提问作者Christian Lowe
相关产品推荐
相关产品推荐

