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:
- 表单验证通过后,Quiz会被真正存到数据库,生成一个数字id
- 重定向到新增问题页面时,URL会变成
/quiz/1/newquestion(比如id是1) - NewQuestion视图能正确找到对应的Quiz,不会再出现id类型不匹配的错误啦~
内容的提问来源于stack exchange,提问作者habti habtamu
相关产品推荐
相关产品推荐

