I have written this endpoint:
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import AsyncSession
from starlette import status
from starlette import status
# Local Imports
from database import SessionLocal
# from .auth import CreateUserRequest, db_dependency, user_dependency
from models import Patients, Users
router =APIRouter(
prefix='/patient',
tags=['patient']
)
async def get_db():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
db = SessionLocal()
try:
yield db
finally:
await db.close()
# Annotation for our database for dependency injection
db_dependency = Annotated[AsyncSession, Depends(get_db)]
async def get_curent_user(token: Annotated[str, Depends(oauth2_bearer)]):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
email: str = payload.get('sub')
user_id: int = payload.get('id')
role_id: int = payload.get('role_id')
if email is None or user_id is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate user."
)
return {'username': email, 'id': user_id, 'role_id': role_id}
except JWTError:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED,
detail='Could not validate user.')
user_dependency = Annotated[dict, Depends(get_curent_user)]
class CreateUserRequest(BaseModel):
username: str # Email is username
password: str
phone: str
dob: date
role_id: int
class CreatePatinetReuqest(BaseModel):
name: str
registration_date: date
user_id: int
@router.post("/add_patient/")
async def add_patient(db: db_dependency, create_user_request: CreateUserRequest):
# Create a new user (patient)
create_user_model = Users(
email=create_user_request.username,
password=None,
phone=create_user_request.phone,
date_of_birth=create_user_request.dob,
role_id=0,
)
try:
db.add(create_user_model)
await db.commit()
except IntegrityError as er:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail=f"User {create_user_request.username} already exists. Choose a different username."
)
await db.refresh(create_user_model)
# Create a corresponding patient entry
add_patient_model = Patients(
registration_date=date.today(),
user_id=create_user_model.id
)
try:
db.add(add_patient_model)
await db.commit()
except IntegrityError as er:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail=f"Patient with {add_patient_model.patient_id} already exists."
)
await db.refresh(add_patient_model)
return {
"message": "Patient added successfully",
"patient_id": add_patient_model.patient_id
}
then I have main.py
from fastapi import FastAPI
from routers import patient
app = FastAPI()
app.include_router(patient.router)
But I am getting unprocessable entity error 422.
I have password set to None because in Users table it is nullable. and what is loc is body?
The error you are encountering is related to the fact that the password field is missing in your request body when calling the /add_patient/ endpoint. This happens because your CreateUserRequest model expects a password field, but in your current add_patient function, you are not using this password field properly.
for you to handle password filed properly in add_patient change this:
class CreateUserRequest(BaseModel):
username: str # Email is username
password: str
phone: str
dob: date
role_id: int
to this
class CreateUserRequest(BaseModel):
username: str
password: Optional[str] = Field(None, description="Password is not required and will be set to None.")
phone: str
dob: date
role_id: int