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

Django测验应用出现ValueError错误:字段'id'期望数字类型但传入'None' 求助

搞定这个ValueError的详细方案

嘿,我来帮你捋清楚这个错误的来龙去脉,然后一步步解决它~

问题到底出在哪?

你看到的ValueError at /quiz/None/newquestion,核心原因是你创建Quiz的时候,还没把它存到数据库就去拿id了!

具体来说:

  • 在NewQuiz视图里,你用了quiz= quizForm.save(commit=False),这只会在内存里生成Quiz对象,根本没写入数据库,所以quiz.id此时是None。
  • 之后你重定向到new-question时,传的quiz_id=quiz_id其实是None,导致URL变成了/quiz/None/newquestion。
  • 就算你把URL改成<int:quiz_id>,但因为传的是None,Django要么匹配不到路由(404),要么把'None'当字符串传给视图,而Quizzes的id是整数类型,自然就报错说“期望数字,却得到了'None'”。

另外,你的urls.py里还有重复的路由(比如check-marks和calculate-marks各有两个),这会搞乱Django的路由匹配,也得一起改。

一步步解决问题

1. 先把Quiz真正存到数据库再拿id

修改NewQuiz视图,确保Quiz对象保存后再获取id,还要处理表单验证失败的情况(别直接重定向,不然用户看不到错误提示):

def NewQuiz(request):
    quizForm = forms.QuizForm()
    if request.method == 'POST':
        quizForm = forms.QuizForm(request.POST)
        if quizForm.is_valid():
            # 直接保存,写入数据库后才会生成有效的id
            quiz = quizForm.save()
            quiz_id = quiz.id
            
            # 如果需要给Quiz加额外字段(比如关联当前用户),可以这么写:
            # quiz = quizForm.save(commit=False)
            # quiz.user = request.user  # 假设你的Quizzes模型有user字段
            # quiz.save()
            # quiz_id = quiz.id
        else:
            print("form is invalid")
            # 验证失败返回原页面,让用户看到错误
            return render(request, 'quiz/createquiz.html', {'quizForm': quizForm})
        return redirect('quiz:new-question', quiz_id=quiz_id)
    return render(request, 'quiz/createquiz.html', {'quizForm': quizForm})

2. 清理urls.py里的重复路由,严格限制参数类型

把重复的路由删掉,并且用<int:quiz_id>确保只有数字能匹配这个参数:

from django.urls import path
from . import views
app_name = "quiz"
urlpatterns = [
    path('quiz/newquiz', views.NewQuiz, name='new-quiz'),
    # 用<int:quiz_id>强制参数为整数
    path('quiz/<int:quiz_id>/newquestion', views.NewQuestion, name='new-question'),
    path('quiz/<int:quiz_id>/quizdetail', views.QuizDetail, name='quiz-detail'),
    path('quiz/<int:quiz_id>/take', views.TakeQuiz, name='take-quiz'),
    # 保留一个正确的check-marks路由
    path('check-marks/<int:quiz_id>', views.check_marks_view, name='check-marks'),
    # 保留一个calculate-marks路由
    path('quiz/calculate-marks', views.calculate_marks_view, name='calculate-marks'),
]

3. 可选:优化NewQuestion的错误反馈

同样,当Question表单验证失败时,别直接重定向,返回原页面让用户看到错误:

def NewQuestion(request, quiz_id):
    user = request.user
    quiz = get_object_or_404(Quizzes, id=quiz_id)
    questionForm = forms.QuestionForm()
    if request.method == 'POST':
        questionForm = forms.QuestionForm(request.POST)
        if questionForm.is_valid():
            question = questionForm.save(commit=False)
            question.quiz = quiz
            question.save()
        else:
            print("form is invalid")
            # 验证失败返回原页面,携带错误信息
            return render(request, 'quiz/createqusetion.html', {'questionForm': questionForm, 'quiz': quiz})
        return redirect('quiz:new-question', quiz_id=quiz_id)
    return render(request, 'quiz/createqusetion.html', {'questionForm': questionForm, 'quiz': quiz})

验证修改

做完这些之后,再去创建Quiz:

  1. 表单验证通过后,Quiz会被真正存到数据库,生成一个数字id
  2. 重定向到新增问题页面时,URL会变成/quiz/1/newquestion(比如id是1)
  3. NewQuestion视图能正确找到对应的Quiz,不会再出现id类型不匹配的错误啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 06:53:23