Django提交职位添加表单触发created_by_id非空约束IntegrityError问询
报错根因
视图层代码存在执行顺序错误:调用form.save(commit=True)时,Django会立刻将表单对应的Job实体写入数据库,此时created_by外键字段尚未完成赋值。由于模型定义中created_by是无空值约束的必填外键,数据库层会直接触发完整性校验错误,后续给job.created_by赋值、二次保存的代码完全没有执行机会,因此会抛出NOT NULL constraint failed: jobs_job.created_by_id报错。
你之前尝试的两项排查操作无法解决问题的原因:
- 单独移除
commit=True参数没有生效:ModelForm的save()方法默认入参就是commit=True,如果只是删掉参数写form.save(),本质和之前的执行逻辑完全没有区别,依然会在未赋值created_by的阶段就直接把数据写入数据库触发报错 - 删除数据库重跑迁移完全不解决问题,因为报错和数据库表结构无关,纯粹是视图层的代码执行逻辑错误
代码调整方法
按照Django ModelForm处理非表单字段的标准流程调整保存逻辑:
- 调用
form.save(commit=False):仅根据表单提交的内容生成对应的Job模型实例,不立刻执行数据库写入操作 - 给非表单提交的必填字段
created_by赋值当前登录用户 - 待所有字段补全后,再调用模型实例的
save()方法正式写入数据库
调整完成后的add_job视图参考代码:
@login_required def add_job(request): if request.method == 'POST': form = AddJobForm(request.POST) if form.is_valid(): # 生成未落地的模型实例,不直接写库 job = form.save(commit=False) # 关联当前登录用户作为职位创建人 job.created_by = request.user # 字段补全完成后正式写入数据库 job.save() return redirect('dashboard') else: form = AddJobForm() return render(request, 'jobs/add_job.html', {'form': form})
注意:
commit=False是ModelForm处理场景的通用实现,适用于所有需要补充非用户输入字段(比如关联当前登录用户、设置操作来源、关联所属组织等)的场景,这类场景下绝对不能直接触发带默认commit=True的保存动作,否则只要模型存在表单未覆盖的必填非空字段,必然会触发数据库约束报错。
内容的提问来源于stack exchange,提问作者user9900365
相关产品推荐
相关产品推荐

