Django表单验证通过但save后对象为None问题求助
问题排查与解决方案
我尝试过两个相关方法但都没解决问题,现在的情况是:用表单创建新对象,部分数据来自用户输入,部分由系统提供。POST请求处理时,表单验证通过且cleaned_data数据正确,但保存后对象显示为None,没有任何内容写入数据库。
打印结果
Cleaned data is: {'exercise': <Exercise: Deadlift>, 'actual_weight': 225.0, 'actual_reps': 12, 'actual_difficulty': 'easy'} Set is Set object (None) set saved
相关代码
views.py
def add_set_to_active_workout(request): workout = get_active_workout() if request.method == "POST": form = SetForm(request.POST) if form.is_valid(): print(f"Cleaned data is: {form.cleaned_data}") # 打印的用户提交数据符合预期 set = form.save(commit=False) set.workout = workout print(f"Set is {set}") # 输出:Set is Set object (None) set.save() print("set saved") return HttpResponseRedirect(reverse("log:active_workout")) else: return render(request, "log/active_workout.html", { "set_form": form, 'workout': workout }) else: return render(request, "log/active_workout.html", { "set_form": SetForm(), 'workout': workout, })
forms.py
class SetForm(forms.ModelForm): class Meta: model = Set fields = ['exercise', 'actual_weight', 'actual_reps', 'actual_difficulty']
models.py
class Set(models.Model): exercise = models.ForeignKey(Exercise, related_name="sets", on_delete=models.SET("Exercise Deleted!")) workout = models.ForeignKey(Workout, related_name="sets", on_delete=models.CASCADE) actual_reps = models.PositiveSmallIntegerField() actual_weight = models.FloatField() difficulty_options = ( ("easy", "easy"), ("medium", "medium"), ("hard", "hard") ) actual_difficulty = models.CharField(choices=difficulty_options, max_length=6) set_complete = models.DateTimeField(auto_now_add=True)
template.html
<h2>Add a Set:</h2> <form action="{% url 'log:add_set_to_active_workout' %}" method="POST"> {% csrf_token %} {{ set_form.as_p }} <input type="submit" value="Save Set" class="btn btn-secondary"> </form>
问题排查方向及解决方法
检查
get_active_workout()的返回值
这是最可能的问题根源:- 在
views.py中添加打印,确认workout是否为有效实例:workout = get_active_workout() print(f"Active workout: {workout}") - 如果返回
None,说明没有找到活跃的Workout对象,需要修复get_active_workout()的逻辑,确保它返回一个已保存到数据库的Workout实例。 - 如果返回的是未保存的Workout对象(即没有主键
pk),先将Workout保存到数据库后再关联Set。
- 在
捕获保存时的异常
在set.save()处添加异常捕获,查看具体错误信息:try: set.save() print(f"Set saved successfully, pk: {set.pk}") except Exception as e: print(f"Save error: {str(e)}")常见错误可能是Workout外键为空、关联的Exercise不存在等。
避免使用Python内置类型作为变量名
变量名set是Python内置集合类型,建议改为new_set或set_instance,避免潜在的命名冲突:new_set = form.save(commit=False) new_set.workout = workout new_set.save()
内容的提问来源于stack exchange,提问作者BLimitless
相关产品推荐
相关产品推荐

