django报错 duplicate key value violates unique constraint “accounts_customuser_phone_key“
·
报错内容
duplicate key value violates unique constraint "accounts_customuser_phone_key"
DETAIL: Key (phone)=() already exists.代码如下: /dc_pywebs/gs_be/./website/apps/accounts/views/reset_pwd.py, line 50, in process_reset_password_data
serializer.is_valid(raise_exception=True)
data = serializer.validated_data.copy()
password = data.pop('password')
user = get_user_by_verification_id(data['email'], require_verified=False)
user.set_password(password)
user.save()
你遇到的错误是:
duplicate key value violates unique constraint "accounts_customuser_phone_key"
DETAIL: Key (phone)=() already exists.
这是典型的数据库层错误,来自 PostgreSQL,它提示你试图保存一个用户对象时,phone 字段违反了唯一约束。换句话说:你试图把一个已经存在的手机号(或者是空值)保存给另一个用户。
🔍 问题分析:
你的代码中:
user = get_user_by_verification_id(data['email'], require_verified=False)
user.set_password(password)
user.save()
你只设置了密码,并没有修改 phone 字段,但是 user.save() 保存整个对象时,Django ORM 会尝试把当前的 user.phone 一起写入数据库。
✅ 可能原因:
1. phone 字段为 "" 或 None,而数据库要求唯一
- 数据库中已有一条记录的
phone=""或phone IS NULL。 - 你当前这条更新的数据,也尝试保存
phone="",导致冲突。
2. get_user_by_verification_id() 获取到了一个用户,但其 phone 值与你数据库中已有用户冲突。
💡 解决方案
✅ 方案 1:在保存前明确设置或跳过 phone 字段
你可以只更新密码而不动其他字段。比如:
user.set_password(password)
user.save(update_fields=['password'])
✅ 这样只更新
password字段,不会触发phone的冲突。
✅ 方案 2:明确检查 phone 字段状态
在保存前检查:
print(f"user.phone: {user.phone!r}")
看看是不是 None、"" 或错误的值,导致唯一冲突。
✅ 方案 3:修改数据库字段逻辑(仅限你控制 schema)
如果你允许多个用户手机号为空,可以修改数据库字段 phone:
CREATE UNIQUE INDEX unique_phone_not_null ON accounts_customuser(phone) WHERE phone IS NOT NULL;
这样只有非空的手机号才必须唯一,空的可以重复。
✅ 建议的最终代码改法(安全)
user.set_password(password)
user.save(update_fields=['password'])
更多推荐
所有评论(0)