Django外键字段赋值报错:必须传入对应模型实例
报错信息
Cannot assign "'1'": "Faculty_Feedback.department" must be a "Department" instance.
报错原因
Django模型的ForeignKey外键字段直接赋值时,要求传入关联模型的实例对象。通过request.POST.get()从表单拿到的参数是字符串类型的主键值,直接赋值给外键字段就会触发上述类型不匹配错误。
另外你定义的resp1到resp13都是IntegerField类型,直接传入POST拿到的字符串值也存在类型校验风险。
解决方法
两种常用合法写法,按需选择即可:
方法1:直接赋值外键对应主键(最简便)
Django的外键字段会自动生成一个字段名_id的隐藏属性,支持直接传入主键值,不需要提前查询数据库获取模型实例,修改后的核心代码如下:
def feedback(request): if request.method == "POST": # POST拿到的是字符串,显式转成整数匹配主键、整数字段类型 dept_id = int(request.POST.get('department')) prog_id = int(request.POST.get('program')) q1 = int(request.POST.get('f1')) q2 = int(request.POST.get('f2')) q3 = int(request.POST.get('f3')) q4 = int(request.POST.get('f4')) q5 = int(request.POST.get('f5')) q6 = int(request.POST.get('f6')) q7 = int(request.POST.get('f7')) q8 = int(request.POST.get('f8')) q9 = int(request.POST.get('f9')) q10 = int(request.POST.get('f10')) q11 = int(request.POST.get('f11')) q12 = int(request.POST.get('f12')) q13 = int(request.POST.get('f13')) com1 = request.POST.get('com1') com2 = request.POST.get('com2') save_feedback = Faculty_Feedback( department_id = dept_id, program_id = prog_id, resp1=q1, resp2=q2, resp3=q3, resp4=q4, resp5=q5, resp6=q6, resp7=q7, resp8=q8, resp9=q9, resp10=q10, resp11=q11, resp12=q12, resp13=q13 ) save_comments = Faculty_Comments( department_id = dept_id, program_id = prog_id, comment_1 = com1, comment_2 = com2 ) save_feedback.save() save_comments.save()
方法2:查询关联实例后再赋值
如果需要校验传入的部门、专业ID真实存在,避免非法主键触发数据库约束报错,可以先查库拿到对应模型实例再赋值给外键:
from django.shortcuts import get_object_or_404 def feedback(request): if request.method == "POST": dept_id = request.POST.get('department') prog_id = request.POST.get('program') # 传入ID不存在时直接返回404,不会抛出数据库级报错 dept = get_object_or_404(Department, pk=dept_id) prog = get_object_or_404(Program, pk=prog_id) # 评分参数转int、评论参数取值逻辑和方法1一致 q1 = int(request.POST.get('f1')) q2 = int(request.POST.get('f2')) # q3到q13的取值逻辑省略,和方法1完全相同 com1 = request.POST.get('com1') com2 = request.POST.get('com2') save_feedback = Faculty_Feedback( department = dept, program = prog, resp1=q1, resp2=q2, resp3=q3, resp4=q4, resp5=q5, resp6=q6, resp7=q7, resp8=q8, resp9=q9, resp10=q10, resp11=q11, resp12=q12, resp13=q13 ) save_comments = Faculty_Comments( department = dept, program = prog, comment_1 = com1, comment_2 = com2 ) save_feedback.save() save_comments.save()
额外优化建议
- 目前手动逐个获取13个评分参数的代码冗余度很高,可以通过循环批量取值,精简代码量
- 正式环境建议搭配Django Form表单做参数合法性校验,避免非法参数传入触发服务端500错误
- 涉及两张表写入的操作建议加数据库事务,避免出现反馈数据、评论数据单表保存成功的不一致问题
内容的提问来源于stack exchange,提问作者Amiable.Azam
相关产品推荐
相关产品推荐

