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 fromBaseUser
, so it expects all the fields that you're declaring there, unless they have a default value. If you don't pass theid
field in your request, it will never work - Have you checked that the
register
method actually sends data in theJSON
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