marius j
marius j

Reputation: 25

Problems understanding Pydantic model with metaclasses/ aliases mapping when using SqlAlchemy

I'm trying to have my Pydantic/ORM models "output" labels,but when using SqlAlchemy ORM I feel a bit locked/ stuck.

I want the fieldname "test1" ( below in the code) to return ( "Test left side") instead of test1 in the JSONResponse

As an explanation, In sql i would for example use “as”

select test1 as ‘Test left side’ from pretest

I know I can do the same in an ORM statement/query, but I want it to be reachable as a field/ attribute from the orm model class, or perhaps as some validation methods from my Pydantic model.

To explain I have added an example of two short models below

my model in Sqlalchemy:

class Pretest(Base):

    __tablename__ = "pretest"

    user_id = Column(Integer)
    pretest_id = Column(Integer, primary_key=True)
    timestamp_pretest = Column(DateTime(timezone=True), default=func.now())
    test1 = Column(Integer)

my model in Pydantic: ( I use Optional because im testing at the moment)

class Pretest(BaseModel):
    user_id: Optional[int] = None
    pretest_id: Optional[int] = None
    timestamp_pretest: Optional[datetime] = None
    test1: Optional[int] = None

    class Config:
         orm_mode= True

So I’m wondering if Pydantic have a possibility to validate against a labelslist/array/ object that could contain a type of test1= “Test left side” Or if the ORM models have some additional metadata that could be used like

test1 = Column(Integer, alias=“Test left side”)

I hope I make this question understandable?

My endpoint look a bit simplified something like this:

@router.post("/pretest", tags=["Medicaldata"], status_code=status.HTTP_200_OK)
def pretest(pretest: Pretest, token: str = Depends(oauth2_scheme)):
    try:    
        query = db.query(models.Pretest).first()
    except:
        query = "query failed"
    return JSONResponse(content=query)

Where I use the pretest-object which is type defined by the Pydantic model as query parameters( not shown here) This response will create a json-object of the fields and values in the database.

The field/variable test1 will return as test1 instead of "Test left side", since I do not have a place to add labels or some sort of aliases.

I can add and map the json object manually in Python before I return it, but it’s a lot of complex queries spanning several tables, so it feels a bit “wrong” to do it that way.

The reason for all this is so that I can have model and label consistency and use the map function with spread operators in components in React as shown below.

get_backend(“/pretest”,data)
.then setPretestlist(response)

{pretestlist.map((item) => {
      return <ShowPretest {...item} key={item.name} />;
     })}

This will now show as test1 in the webpage instead of a more explanatory text like this "Test 1 left side"

Upvotes: 0

Views: 795

Answers (1)

marius j
marius j

Reputation: 25

@snakecharmerb, Thx, you put me on the right track.

The solution, if someone else wonder: the Pydantic model needs to be changed from this:

class Pretest(BaseModel):
    user_id: Optional[int] = None
    pretest_id: Optional[int] = None
    timestamp_pretest: Optional[datetime] = None
    test1: Optional[int] = None

    class Config:
         orm_mode = True

To this:

class Pretest(BaseModel):
    user_id: Optional[int] = None
    pretest_id: Optional[int] = None
    timestamp_pretest: Optional[datetime] = None
    test1: Optional[int] = None

    class Config:
      fields = {
         "test1": "Test left side",
         "timestamp_pretest": "Time tested",
      }
         orm_mode = True

The endpoint needed to change in the way it does its response to this:

@router.post("/pretest", tags=["Medicaldata"], status_code=status.HTTP_200_OK)
def pretest(pretest: Pretest, token: str = Depends(oauth2_scheme)):
    try:    
        query = db.query(models.Pretest).first()
        query = Pretest.from_orm(query)
    except:
        query = "query failed"

    return query.dict(by_alias=True)

Upvotes: 0

Related Questions