Vitalii Mytenko
Vitalii Mytenko

Reputation: 772

FastAPI gives "value is not a valid dict (type=type_error.dict)"

I'm learning FastAPI on this project and faced the issue - any request no matter GET or POST throws me an error: value is not a valid dict (type=type_error.dict). What is wrong with my code. My models.py

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True)
    telegram_id = Column(Integer, unique=True, index=True)
    username = Column(String(50))
    pet_name = Column(String(50))
    language_code = Column(String(5))

    sent_items = relationship("Log", back_populates="recipient")

class Log(Base):
    __tablename__ = "sent_log"

    id = Column(Integer, primary_key=True, index=True)
    user_id = Column(Integer, ForeignKey("users.id"))
    recipient = relationship("User", back_populates="sent_items")

    article_id = Column(Integer, ForeignKey("articles.id"))
    article = relationship("Article", back_populates="items")

class Article(Base):
    __tablename__ = "articles"

    id = Column(Integer, primary_key=True, index=True)
    text = Column(String(1024))
    image_url = Column(String(500), index=True)
    language_code = Column(String(255))

    items = relationship("Log", back_populates="article")

schemas:

class ArticleBase(BaseModel):
    text: str
    image_url: str
    language_code: str

class ArticleCreate(ArticleBase):
    pass

class ArticleEdit(ArticleBase):
    id: int

    class Config:
        orm_mode = True

class UserBase(BaseModel):
    telegram_id: int
    username: str
    pet_name: str
    language_code: str

class UserCreate(UserBase):
    pass

class UserEdit(UserBase):
    id: int

    class Config:
        orm_mode = True

crud.py

def get_articles(db: Session, skip: int = 0, limit: int = 100):
    """Get all articles."""
    return db.query(models.Article).offset(skip).limit(limit).all()


def get_article(db: Session, article_id: int):
    """Get article by id."""
    return db.query(models.Article).filter(models.Article.id == article_id).first()


def create_article(db: Session, article: schemas.ArticleCreate):
    db_article = models.Article(
        text=article.text,
        image_url=article.image_url,
        language_code=article.language_code
    )
    db.add(db_article)
    db.commit()
    db.refresh(db_article)
    return db_article

main.py

@app.get("/users/{user_telegram_id}", response_model=schemas.UserBase, tags=["user"])
def read_user(user_telegram_id: int, db: Session = Depends(get_db)):
    db_user = crud.get_user(db, user_telegram_id=user_telegram_id)
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    return db_user


@app.post("/articles/", response_model=schemas.ArticleCreate, tags=["article"])
def create_article(article: schemas.ArticleCreate, db: Session = Depends(get_db)):
    return crud.create_article(db=db, article=article)


@app.get("/articles/", response_model=schemas.ArticleBase, tags=["article"])
def read_articles(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    items = crud.get_articles(db, skip=skip, limit=limit)
    return items


@app.get("/articles/{article_id}", response_model=schemas.ArticleBase, tags=["article"])
def read_article(article_id: int, db: Session = Depends(get_db)):
    db_article = crud.get_article(db, article_id=article_id)
    if db_article is None:
        raise HTTPException(status_code=404, detail="Article not found")
    return db_article

By the way, @app.post("/articles/"... throws an error, but also inserts a data in DB.

Upvotes: 3

Views: 11852

Answers (2)

Vitalii Mytenko
Vitalii Mytenko

Reputation: 772

The problem was here - might to add list[schemas.ArticleBase] for returning multiply items:

@app.get("/articles/", response_model=list[schemas.ArticleBase], tags=["article"])
def read_articles(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    items = crud.get_articles(db, skip=skip, limit=limit)
    return items

Upvotes: 2

fchancel
fchancel

Reputation: 2699

The problem is in your return, that's why the insertion in the db works. You want to return the ArticleCreate schema (response_model=schemas.ArticleCreate) except that you return your database response directly without any formatting. So you have to convert your crud response into your schema response.

@app.post("/articles/", response_model=schemas.ArticleCreate, tags=["article"])
def create_article(article: schemas.ArticleCreate, db: Session = Depends(get_db)):
    response = crud.create_article(db=db, article=article)
    return schemas.ArticleCreate(**response.dict())

or simply use the orm mode inside your ArticleCreate class

Upvotes: 5

Related Questions