报错内容

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'])
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐