0

我想优化我的 API 对数据库的调用量。但是是否可以让 Postgres 遇到唯一约束错误。例如,在注册用户时,我有两个选择:

from app.models import Users
from tortoise.exceptions import DoesNotExist

try:
    await Users.get(email=email)
    raise HTTPException(
        status_code=HTTP_400_BAD_REQUEST, detail="User already exists"
    )
except DoesNotExist:
    user = await Users.create(email, hashed_pw)

这将对数据库进行两次调用,但在 Python 中会发生异常。请注意,在 postgres 结束时不会引发任何错误或异常。Postgres 只返回 nill,它在 python 端被解释为 DoesNotExist。另一种解决方案是:

from app.model import Users
from asyncpg.exceptions import UniqueViolationError

try:
    user = await Users.create(email, hashed_pw)
except UniqueViolationError:
    raise HTTPException(
        status_code=HTTP_400_BAD_REQUEST, detail="User already exists"
    )

这只会进行一次数据库调用,但是在 postgres 数据库中会发生错误。显然,在我看来,第二个实现会更有效,但是在 postgres 端创建一个异常可以吗?

4

1 回答 1

1

只有当您涉及事务或锁定时,您的第一个代码才能可靠地工作。否则,如果创建具有相同电子邮件的用户的两个请求(我知道在这种情况下不太可能)命中您的 API,那么两者都可能得到DoesNotExist结果并执行await Users.create(email, hashed_pw)。这种模式通常是不鼓励的。

此外,对控制流使用异常也是通常被视为不好的做法。

您的第二个解决方案很好,尝试创建一个条目并使用 postgres 发出的期望来告诉请求用户已经存在是没有问题的。

如果您有交易并且有类似的函数await Users.exists(email=email)返回 true 或 false,那么第一个会很好。

就个人而言,我更喜欢第二个,因为唯一约束已经做了你想做的检查,但是你需要确保你真正检查你得到的错误消息是否是关于唯一键的,email而不是关于其他错误的。

于 2022-02-17T19:15:49.067 回答