question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[QUESTION] Getting Validation Error on Response, using Alchemysql + FastAPI

See original GitHub issue

Description

i’m getting a validation error on my API, not sure what’s wrong with it, i followed the example at SQL (Relational) Databases i think it’s a problem with the pydantic models, i’m still not sure if defining it correctly.

here’s the package version that i’m using

  • fastapi 0.63.0
  • pydantic 1.7.3
  • SQLAlchemy 1.3.22

here’s the error Traceback

2021-01-12 20:38:26,463 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2021-01-12 20:38:26,464 INFO sqlalchemy.engine.base.Engine SELECT device.id AS device_id, device.macaddress AS device_macaddress, device.name AS device_name
FROM device
2021-01-12 20:38:26,465 INFO sqlalchemy.engine.base.Engine ()
2021-01-12 20:38:26,478 INFO sqlalchemy.engine.base.Engine SELECT record.id AS record_id, record.timestamp AS record_timestamp, record.image AS record_image, record.reading AS record_reading, record.device_id AS record_device_id
FROM record
WHERE ? = record.device_id
2021-01-12 20:38:26,479 INFO sqlalchemy.engine.base.Engine (1,)
2021-01-12 20:38:26,481 INFO sqlalchemy.engine.base.Engine SELECT record.id AS record_id, record.timestamp AS record_timestamp, record.image AS record_image, record.reading AS record_reading, record.device_id AS record_device_id
FROM record
WHERE ? = record.device_id
2021-01-12 20:38:26,482 INFO sqlalchemy.engine.base.Engine (2,)
INFO:     127.0.0.1:64156 - "GET /devices/ HTTP/1.1" 500 Internal Server Error
2021-01-12 20:38:26,484 INFO sqlalchemy.engine.base.Engine ROLLBACK
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "e:\repo\tubes iot\env\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 394, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "e:\repo\tubes iot\env\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "e:\repo\tubes iot\env\lib\site-packages\fastapi\applications.py", line 199, in __call__
    await super().__call__(scope, receive, send)
  File "e:\repo\tubes iot\env\lib\site-packages\starlette\applications.py", line 111, in __call__
    await self.middleware_stack(scope, receive, send)
  File "e:\repo\tubes iot\env\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
    raise exc from None
  File "e:\repo\tubes iot\env\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "e:\repo\tubes iot\env\lib\site-packages\starlette\exceptions.py", line 82, in __call__
    raise exc from None
  File "e:\repo\tubes iot\env\lib\site-packages\starlette\exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "e:\repo\tubes iot\env\lib\site-packages\starlette\routing.py", line 566, in __call__
    await route.handle(scope, receive, send)
  File "e:\repo\tubes iot\env\lib\site-packages\starlette\routing.py", line 227, in handle
    await self.app(scope, receive, send)
  File "e:\repo\tubes iot\env\lib\site-packages\starlette\routing.py", line 41, in app
    response = await func(request)
  File "e:\repo\tubes iot\env\lib\site-packages\fastapi\routing.py", line 209, in app
    response_data = await serialize_response(
  File "e:\repo\tubes iot\env\lib\site-packages\fastapi\routing.py", line 126, in serialize_response
    raise ValidationError(errors, field.type_)
pydantic.error_wrappers.ValidationError: 4 validation errors for Device
response -> 0 -> maccaddress
  field required (type=value_error.missing)
response -> 0 -> records -> 0 -> reading
  none is not an allowed value (type=type_error.none.not_allowed)
response -> 0 -> records -> 1 -> reading
  none is not an allowed value (type=type_error.none.not_allowed)
response -> 1 -> maccaddress
  field required (type=value_error.missing)

schemas.py

from typing import List, Optional
from pydantic import BaseModel

import datetime
class Record(BaseModel):
    id : int
    timestamp : datetime.datetime
    image : Optional[str]
    device_id : int
    reading : int

    class Config :
        orm_mode= True

class Device(BaseModel):
    id : int
    maccaddress : str
    name : Optional[str] = None
    records : List[Record] =[]

    class Config : 
        orm_mode = True
class DeviceChange(Device):
    name : str

models.py

class Device(Base):
    __tablename__ = 'device'
    id = Column(Integer, primary_key=True)
    macaddress = Column(String, unique=True)
    name = Column(String)

    records = relationship("Record",back_populates='device')

class Record(Base):
    __tablename__ = 'record'
    id = Column(Integer, primary_key=True)
    timestamp = Column(DateTime(timezone=False),default=func.now())
    image = Column(String) 
    reading = Column(Integer)
    device_id = Column(Integer, ForeignKey('device.id'))
    
    device = relationship("Device",back_populates='records')

crud.py

from sqlalchemy.orm import Session
import models, schemas, datetime

def get_devices(db : Session) : 
    return db.query(models.Device).all()

def get_device(db : Session, dev_id : int) :
    return db.query(models.Device).filter(models.Device.id == dev_id).first()

def get_records(db : Session, date: datetime, dev_id : int) : 
    return db.query(models.Record).filter(
        (models.Record.timestamp.like('%'+date+'%')),
        (models.Record.device_id == dev_id)
    ).all()

def set_name(db : Session, name : str, dev_id : int):
    query = db.query(models.Device).filter(
        models.Device.id == dev_id
    ).first()
    query.name = name
    db.commit()
    return query

main.py

app = FastAPI()

# Dependency
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()
# Return all Devices
@app.get("/devices/", response_model=List[schemas.Device])
def read_devices(db : Session = Depends(get_db)):
    devices = crud.get_devices(db)
    return devices

# Return Device 
@app.get("/devices/{device_id}", response_model=schemas.Device)
def read_device(device_id : int,db : Session = Depends(get_db)):
    device = crud.get_device(db,device_id)
    return device

# Return device records list
@app.get("/devices/{device_id}/records/{date}", response_model=List[schemas.Record])
def read_records(date : datetime.datetime, device_id : int, db : Session = Depends(get_db)):
    records = crud.get_records(db,date,device_id)
    return records

# Return Device latest record
@app.get("/devices/{device_id}/records/latest", response_model=schemas.Record)
def read_latest(device_id : int, db : Session = Depends(get_db)):
    record = crud.get_latest(db,device_id)
    return record.reading

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

7reactions
GagahGKcommented, Jan 12, 2021

Update : i fixed the problem by changing the pydantic variable in Record Class to optional

class Record(BaseModel):
    id : int
    timestamp : datetime.datetime
    image : Optional[str]
    device_id : int
    reading : Optional[int]

    class Config :
        orm_mode= True

thanks everyone i’m really sorry for creating stupid issues like this

1reaction
tiangolocommented, Nov 10, 2022

Thanks for the help here everyone! 👏 🙇

Thanks for reporting back and closing the issue 👍

Sorry for the long delay! 🙈 I wanted to personally address each issue/PR and they piled up through time, but now I’m checking each one in order.

Read more comments on GitHub >

github_iconTop Results From Across the Web

FastApi get request shows validation error - Stack Overflow
So with this schema i get the same error response -> name field required (type=value_error.missing) response -> value field required ...
Read more >
Handling Errors - FastAPI
These handlers are in charge of returning the default JSON responses when you raise an HTTPException and when the request has invalid data....
Read more >
Many-To-Many Relationships In FastAPI - GormAnalysis
In this tutorial, I cover multiple strategies for handling many-to-many relationships using FastAPI with SQLAlchemy and pydantic.
Read more >
How to Implement Pagination Using FastAPI in Python
Use fastapi -pagination library to paginate API responses ... Note: If you get duplicate key errors, try inserting fewer rows at a time...
Read more >
FastAPI with SQLAlchemy Tutorial - YouTube
In this video, Jose Haro Peralta explains how to use SQLAlchemy in a FAstAPI application.The code for this tutorial is available in GitHub: ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found