You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

问题排查方向及解决方法

  1. 检查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。
  2. 捕获保存时的异常
    在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不存在等。

  3. 避免使用Python内置类型作为变量名
    变量名set是Python内置集合类型,建议改为new_set或set_instance,避免潜在的命名冲突:

    new_set = form.save(commit=False)
    new_set.workout = workout
    new_set.save()
    

内容的提问来源于stack exchange,提问作者BLimitless

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 22:54:56