how can i make a key dynamic in a pydantic model [closed]

i have an api entrypoint:

@app.get('/dealers_get_users/', response_model = schemas.SellSideUserId, status_code=200)
def getdata(db: database.SessionLocal = _Depends(database.get_db)):
    result = {}
    i =  db.query(models.sellSideUser).all()
    for dealer_users in i:
        result[str(dealer_users.user_id)] = {
            'user_name'  :     dealer_users.user_name,
            'user_pass'  :     dealer_users.user_pass,
            }
    m = schemas.SellSideUserId(user_id=result)
    return m

the data coming in from the db is just 3 fields: user_id,user_name,user_pass

when i call the api, i get this:

{
"user_id": {
            "1": {
                  "user_name": "testname",
                  "user_pass": "testpass"
                  }
            }
}

ok, cool – i got my data. but i’m still trying to understand how these models work, and am not really grasping how to move in or out of a nested dictionary.

for example, i would like it to look like this, instead:

{
            "1": {
                  "user_name": "testname",
                  "user_pass": "testpass"
                  }
}

but i’m not sure how to pass the ‘result’ variable into this class – any way i do it, i’m met with an error.

my model:

class SellSideUserId(_BaseModel):
    user_id     : dict
    class Config:
        orm_mode = True

am i supposed to build two pydantic models – one being based on another? could use some help with this

thanks!

Answer

You can easily make a model with dynamic keys using a dict as custom root type:

class User(BaseModel):
    name: str
    password: str

class ProductModel(BaseModel):
    __root__: Dict[str, User]

Moreover, you can constrain dictionary keys using constr сapabilities, such as regex pattern:

UserId = constr(regex=r'^d+$')

class ProductModel(BaseModel):
    __root__: Dict[UserId, User]

This will work well for validating returned responses against your model. But generated OpenAPI schema will be rather scanty, since at the moment FastAPI 0.68 and swagger UI does not support yet OpenAPI 3.1, which contains such keyword as patternProperties or propertyNames.