Django:如何自动为用户模型填充多对多字段关联
解决方案
要实现点击提交按钮就把当前SingleWorkout实例添加到登录用户的completed_workouts多对多字段中,且不显示任何选择框,你需要调整表单和视图的逻辑,具体如下:
1. 简化表单(forms.py)
不需要使用UserChangeForm,因为你不需要用户输入任何字段,直接创建一个空表单即可:
from django import forms class CompleteWorkoutForm(forms.Form): # 空表单,仅用于触发提交逻辑 pass
2. 调整视图逻辑(views.py)
使用FormView(而非UpdateView,因为你不需要更新SingleWorkout实例,只是给用户添加关联),在form_valid方法中完成多对多关系的添加:
from django.views.generic.edit import FormView from django.contrib.auth.mixins import LoginRequiredMixin from django.urls import reverse_lazy from .models import SingleWorkout class WorkoutCompleteView(LoginRequiredMixin, FormView): template_name = 'workout/daily_view.html' form_class = CompleteWorkoutForm success_url = reverse_lazy("template") def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 获取当前页面对应的SingleWorkout实例 context['workout'] = SingleWorkout.objects.get(slug=self.kwargs['slug']) return context def form_valid(self, form): # 获取当前登录用户 current_user = self.request.user # 获取要添加的SingleWorkout实例 target_workout = SingleWorkout.objects.get(slug=self.kwargs['slug']) # 添加到多对多字段 current_user.completed_workouts.add(target_workout) # 执行父类逻辑完成重定向 return super().form_valid(form)
3. 修改模板
移除表单字段的渲染,只保留提交按钮:
{{ workout }} <br> workout: <br> {{ workout.exercise_1 }} <br> {{ workout.description_1 }} <form method="POST"> {% csrf_token %} <!-- 无需显示任何表单字段 --> <input type="submit" value="Confirm"> </form>
关键说明
- 逻辑位置:多对多关系的添加逻辑放在
views.py的form_valid方法中,因为这里需要访问当前请求的用户、URL中的slug参数,这些都属于视图层的上下文数据,放在视图中更合理。 - 表单简化:空表单足够触发提交流程,避免了不必要的字段渲染,符合你“除提交按钮外无其他界面元素”的需求。
- 视图选型:用
FormView替代原有的UpdateView,因为你不需要更新任何模型实例的字段,只是执行一个关联添加操作,FormView的语义更贴合这个场景。
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

