Home > database >  FastAPI - 422 Unprocessable Entity error with Axios call
FastAPI - 422 Unprocessable Entity error with Axios call

Time:12-19

Very new to FastAPI and I'm stumped. I am attempting to register a new user through my api but am receiving this error from my request:

{
    "detail": [
        {
            "loc": [
                "body",
                "id"
            ],
            "msg": "field required",
            "type": "value_error.missing"
        },
        {
            "loc": [
                "body",
                "username"
            ],
            "msg": "field required",
            "type": "value_error.missing"
        },
        {
            "loc": [
                "body",
                "password"
            ],
            "msg": "field required",
            "type": "value_error.missing"
        },
        {
            "loc": [
                "body",
                "email"
            ],
            "msg": "field required",
            "type": "value_error.missing"
        },
        {
            "loc": [
                "body",
                "phone_number"
            ],
            "msg": "field required",
            "type": "value_error.missing"
        }
    ]
}

I am not sure what I am doing wrong or if its a frontend or backend issue. I assume there's something wrong with how I am trying to receive this request with my pydantic model because I can't seem to see an issue on the frontend. My post method on the frontend looks like:

api.js

import axios from 'axios';

const api = axios.create({
    withCredentials: true,
    baseURL: 'http://localhost:8000'
});

api.interceptors.request.use((config) => {
    config.headers = {
        Accept: 'application/json',
        ContentType: "application/json"
    };

    return config;
});

api.interceptors.response.use(
    (response) => response,
    (error) => {
        return Promise.reject(error);
    },
);

export default api;

and my service on the frontend looks like:

function register(user) {
    return api.post('auth/register', user, { withCredentials: true, 'Access-Control-Allow-Origin': '*' })
        .then((response) => response)
        .catch((error) => Promise.reject(error));
}

and then my actual method call:

const handleRegistration = () => {
        setLoading(true);

        let new_user = {
            username: inputs.username,
            password: inputs.password,
            email: inputs.password,
            phone_number: inputs.phone
        }

        AuthService.register(new_user).then(() => {
                setLoading(false);
                navigation.navigate('LoginScreen');
                toast('success', 'Successfully created new account', null);
            },
            (e) => {
                setLoading(false);
                console.log(e.toString());
                toast('error', 'Error creating new account', null);
            })
    }

and last my python user BaseModel and api call look like:

user.py

from pydantic import BaseModel, Field
from .document import DocumentBase


class UserBase(BaseModel):
    id: int
    username: str
    password: str
    email: str
    phone_number: str
    documents: list[DocumentBase] = []

    class Config:
        arbitrary_types_allowed = True
        orm_mode = True

auth.py

@router.post("/register")
def register(data: UserBase, _db: Session = Depends(get_db)):
    # querying database to check if user already exist
    user = _db.query(User).filter(User.email == data.email).first()
    if user is not None:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="User with this email already exist"
        )
    new_user = User()
    new_user.username = data.username
    new_user.password = get_hashed_password(data.password)
    new_user.email = data.email
    new_user.phone_number = data.phone_number

    _db.add(new_user)
    _db.commit()
    return new_user

Any insight to this issue would be greatly appreciated

CodePudding user response:

  • The API accepts data of the from BaseUser, so it expects all the fields that you're declaring there, unless they have a default value. If you don't pass the id field in your request, it will never work
  • Have you checked that the register method actually sends data in the JSON format?

The solution to the first point is to create two models: one for data input, the other for returning data, so that the user cannot set/change internal values. In this case, one may play with the inheritance of models, something like

class userBase(BaseModel):
    # shared fields

class UserInput(userBase):
    # fields dedicated to the input of a user

class UserOutput(userBase):
    # fields dedicated to the output of a user
  • Related