Django表单提交报NOT NULL约束失败: posts_subscribe.firstname
报错原因
- 表单输入控件未配置
name属性:表单通过POST提交数据时,后端是根据控件的name属性来匹配对应取值的,id属性仅用于前端DOM绑定、label关联,不参与表单值提交。当前模板内所有input标签都缺少name属性,直接导致后端request.POST.get()拿不到任何用户输入,所有字段返回值都是None。 - 模型字段约束理解偏差:你给
firstname、secondname加的blank=True仅作用于Django自带的表单验证环节,不会改变数据库层面的非空约束。Django模型字段默认null=False,也就是数据库表的对应字段禁止存入NULL值,当你把取到的None传给firstname字段执行save操作时,就会触发题目中的NOT NULL约束报错。
解决步骤
1. 修复模板表单,为所有input补充对应name属性
给四个输入框分别添加和后端取值名一致的name属性,修改后的表单核心代码如下:
<form method="POST" enctype="multipart/form-data" action="subscribe"> {% csrf_token %} <div class="mb-3 mx-5"> <label for="firstname" class="form-label">First Name</label> <input type="text" name="firstname" class="form-control form-control-lg" id="firstname" placeholder="firstname"> </div> <div class="mb-3 mx-5"> <label for="secondname" class="form-label">Second Name (Optional)</label> <input type="text" name="secondname" class="form-control form-control-lg" id="secondname" placeholder="secondname"> </div> <div class="mb-3 mx-5"> <label for="email" class="form-label">Email</label> <input type="email" name="email" class="form-control form-control-lg" id="email" placeholder="example@example.com"> </div> <div class="mb-3 mx-5"> <label for="phonenumber" class="form-label">Phonenumber</label> <input type="number" name="phonenumber" class="form-control form-control-lg" id="phonenumber" placeholder="0712345678"> </div> <div class="mb-3 mx-5"> <button type="submit" class="btn-primary">Subscribe</button> </div> </form>
2. 修正模型字段配置,匹配业务规则
如果firstname、secondname确实允许用户留空,需要补充null=True开放数据库层面的空值存储权限;另外手机号不建议使用IntegerField存储,会出现长度溢出、前导0被自动清除的问题,建议改为CharField,修改后的模型代码如下:
class Subscribe(models.Model): firstname = models.CharField(max_length=30, blank=True, null=True) secondname = models.CharField(max_length=30, blank=True, null=True) email = models.CharField(max_length=30) phonenumber = models.CharField(max_length=15)
3. 执行数据库迁移同步表结构
修改完模型后,在项目根目录终端执行以下两条命令,将模型改动同步到数据库表:
python manage.py makemigrations python manage.py migrate
可选优化:增加后端取值兜底
可以在调用request.POST.get()时设置空字符串作为默认值,避免极端场景下取值为None的问题:
def subscribe(request): if request.method == 'POST': firstname = request.POST.get('firstname', '') secondname = request.POST.get('secondname', '') email = request.POST.get('email', '') phonenumber = request.POST.get('phonenumber', '') en = Subscribe(firstname=firstname, secondname=secondname, email=email, phonenumber=phonenumber) en.save() return redirect('/') return render(request, 'subscribe.html')
内容的提问来源于stack exchange,提问作者Felicity
相关产品推荐
相关产品推荐

