1

I am writing because I have a problem with fastAPI and postman. I have this post function

@router.post('/', status_code=status.HTTP_201_CREATED)
def create(request: schemas.Blog, db: Session = Depends(get_db), current_user: schemas.User = Depends(oauth2.get_current_user)):
  request_user = db.query(models.User).filter(
                          models.User.email == current_user.email).first()
  print(request_user)
  new_blog = models.Blog(title=request.title,
                         body=request.body, user_id=request_user.id)
  db.add(new_blog)
  db.commit()
  db.refresh(new_blog)
  return new_blog

My models are:


class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True, index=True)
    username = Column(String, unique=True, index=True)
    email = Column(String, unique=True, index=True)
    password = Column(String, unique=False, index=True)

    blogs = relationship('Blog', back_populates='creator')

class Blog(Base):
    __tablename__ = 'blogs'

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String, unique=True, index=True)
    body = Column(String, unique=False, index=True)
    user_id = Column(Integer, ForeignKey('users.id'))

    creator = relationship('User', back_populates='blogs')

    def __str__(self):
        return self.title

And schemas


class Blog(BaseModel):
    title: str
    body: str

    class Config:
        orm_mode = True

So with this setup on my fastAPI docs everything works fine. I can create new blog but when I do exactly same thing in Postman I am getting 422 Unproccessed Entity error

enter image description here

Its really weird because I am doing exactly the same action but in Postman... Does anyone faced problem like this ?

!! EDIT !! Propably its working with forms because of OAuth2PasswordRequestForm but I will keep my question here for deeper explanation :)

I followed Instructions from MatsLindh and it works for now but I have one more question. I understand that my requested had to be in raw data. But I have a function to login and generate JWT token which is working with sending form data in postman. Can you explain me what is making my function acceptable with form data ? Here is function Iam using for login and generate tokens

@router.post('/') def login(request: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(database.get_db)): user = db.query(models.User).filter( models.User.email == request.username).first() if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail='invalid credentials')

if not Hash.verify_password(request.password, user.password):
    raise HTTPException(
        status_code=status.HTTP_404_NOT_FOUND, detail='invalid password')
# generate a jwt token and return
access_token_expires = timedelta(minutes=token.ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = token.create_access_token(
    data={"sub": user.email}, expires_delta=access_token_expires)

And there is create_acces_token function

def create_access_token(data: dict, expires_delta): to_encode = data.copy() if expires_delta: expire = datetime.utcnow() + expires_delta else: expire = datetime.utcnow() + timedelta(minutes=15) to_encode.update({"exp": expire}) encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) return encoded_jwt

Also thank you for suggesting to change name of submitting object, I will change itd Thanks for answers guys ! :)

KarolB
  • 11
  • 3

1 Answers1

0

You're sending form data, not JSON which is what your endpoint expect. Change the setting in Postman: go to "Raw data" and select "JSON" in the pulldown (instead of text as it might as default) and enter the relevant JSON:

{
  'title': 'foo',
  'body': 'body'
}

I also recommend against using request as the variable name for your submitted object, as this is usually used for values from FastAPI's built-in Request object. Instead use blog_post or something similar:

@router.post('/', status_code=status.HTTP_201_CREATED)
def create(blog_post: schemas.Blog, ...):
MatsLindh
  • 49,529
  • 4
  • 53
  • 84