Django模型更新触发IntegrityError:NOT NULL约束失败求助
错误详情
IntegrityError at /configuration/solarwinds/
NOT NULL constraint failed: pages_cityname.name
Django版本:3.2.5
异常类型:IntegrityError
异常值:NOT NULL constraint failed: pages_cityname.name
异常位置:/usr/local/lib/python3.7/site-packages/django/db/backends/sqlite3/base.py第423行
Python可执行文件:/usr/local/opt/python/bin/python3.7
模型定义(models.py)
class Region(models.Model): name = models.CharField(max_length=50) def __str__(self): return self.name class Meta: verbose_name_plural = 'Region' class Cityname(models.Model): region = models.ForeignKey(Region, on_delete=models.CASCADE) name = models.CharField(max_length=40) # 该字段无null/blank属性,强制非空 def __str__(self): return self.name class Meta: verbose_name_plural = 'Cityname' class SolarwindsTool(models.Model): region = models.ForeignKey(Region, on_delete=models.SET_NULL, blank=True, null=True, verbose_name='Region') city = models.ForeignKey(Cityname, on_delete=models.SET_NULL, blank=True, null=True, verbose_name='City') class Meta: db_table = 'solarwindstool' def __str__(self): return self.name # 注意:模型未定义name字段,此处会触发AttributeError
批量创建数据的视图代码(views.py)
myvar = {'Data Centers': ['LAX101', 'LAX100', 'EWR100'], 'Americas': ['MEX01', 'BOU02', 'TOR01', 'LAX55']} for key in sorted(myvar): if Region.objects.filter(name=key).exists(): for items in myvar[key]: if Cityname.objects.filter(name=items).exists(): pass else: b = Region.objects.get(name=key) e = Cityname(region=b, name=items) e.save() else: value = Region(name=key) value.save() print("THIS IS SITE", key) for items in myvar[key]: value2 = Cityname(name=items, region=value) print("THIS IS VALUE2", value2) value2.save()
问题分析与解决方案
错误核心是:尝试创建Cityname实例时,name字段为NULL,违反了模型中name的非空约束(模型未设置null=True或blank=True)。结合代码场景,具体修复方向如下:
修复
SolarwindsTool模型的__str__方法
模型未定义name字段,但__str__尝试返回self.name,会触发AttributeError,可能间接导致数据保存异常。修改为:def __str__(self): return f"{self.region} - {self.city}" if (self.region and self.city) else "Unconfigured"修正
Cityname重复判断逻辑
当前仅通过name判断城市是否存在,但Cityname与Region关联,不同Region下可能有同名城市,会导致误判跳过创建。修改判断条件为同时匹配region和name:# 替换原判断逻辑 if Cityname.objects.filter(region=b, name=items).exists(): pass过滤
myvar中的无效值
检查myvar的列表项,确保无空字符串、空格或None,添加过滤逻辑:for items in myvar[key]: items = items.strip() if not items: continue # 跳过空值 # 后续创建逻辑清理数据库脏数据
检查并删除pages_cityname表中name为空的记录:# 在python manage.py shell中执行 Cityname.objects.filter(name__isnull=True).delete()检查表单提交逻辑
错误发生在/configuration/solarwinds/路由,需确认该页面的表单:- 确保
city字段的下拉选项均为有效的Cityname实例(所有实例name非空) - 表单验证时,确保
city字段提交值对应已存在的Cityname,避免创建空name实例
- 确保
验证步骤
- 运行
python manage.py shell,执行Cityname.objects.filter(name__isnull=True),确认是否存在空name记录 - 打印
myvar中所有items,检查是否有无效值 - 测试
SolarwindsTool的__str__方法,确保无异常 - 重新运行批量创建代码,验证数据是否正确插入
内容的提问来源于stack exchange,提问作者xis10z

