我想優化我的 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 端創建一個例外可以嗎?
uj5u.com熱心網友回復:
Your first code would only work reliably if you have transactions or locking involved. Otherwise, if two requests to create a user with the same email (I know that this is unlikely in this case) hit your API, then both could get DoesNotExist as a result and would executed await Users.create(email, hashed_pw). That kind of pattern is often discouraged.
Also using exceptions for control flow is also something that is often seen as bad practice.
Your second solution is fine, there is no problem with trying to create an entry and use the expectation that is emitted by postgres to tell the request that the user already exists.
The first one would be fine if you have transactions and if you have a function like await Users.exists(email=email) that returns true or false.
Personally, I would prefer the second one, because the unique constraint already does the check you want to do, but you need to ensure that you actually check if the error message you get is about the unique key for email and not about some other error.
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/426705.html
標籤:PostgreSQL 快速API 唯一约束 龟甲
