SQL_CREATE_USER ="insert into users(email,name) values(lower($1),$2) returning id,email,name"
Name = Annotated[str, StringConstraints(strip_whitespace=True, min_length=1, max_length=120)]
class UserIn(BaseModel):
email: EmailStr
name: Name
class UserOut(UserIn):
id:int
@router.post("/users", response_model=UserOut, status_code=201)
async def create_user(u: UserIn) -> UserOut:
try:
row =await pool.fetchrow(SQL_CREATE_USER,str(u.email), u.name)
exceptUniqueViolationErrorasexc:
raiseHTTPException(status_code=409, detail="email already exists")fromexc
ifrowis None:
raiseHTTPException(status_code=500, detail="insert failed")
returnUserOut.model_validate(dict(row))
#[derive(Deserialize, Validate)]
#[serde(deny_unknown_fields)]
pub struct UserIn{
#[validate(email)]
pubemail: String,
#[validate(custom(function ="valid_name"))]
pubname: String,
}
pub async fn create_user(
State(pool): State<PgPool>,
ValidatedJson(u): ValidatedJson<UserIn>,
) ->Result<(StatusCode, Json<UserOut>), ApiError> {
letuser = sqlx::query_as!(UserOut,
"insert into users(email,name) values(lower($1),$2) returning id,email,name",
u.email.as_str(),
u.name.trim(),
)
.fetch_one(&pool)
.await
.map_err(ApiError::from_db)?;
Ok((StatusCode::CREATED, Json(user)))
}