4

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!

avnav99
  • 532
  • 5
  • 16
  • If you want to return more than one user, why don't you use a list instead of a dict? – Hernán Alarcón Sep 20 '21 at 23:11
  • @HernánAlarcón i suppose i can do that, but i'd like to just know how to do this - theres obviously a misunderstanding of how these models work on my part – avnav99 Sep 20 '21 at 23:15
  • 1
    As far as I know, keys in basic pydantic models are not supposed to be dynamic. That is how it is designed. You define them when you write the classes and you can even give them an alias, but that is it. The documentation describes [dynamic model creation](https://pydantic-docs.helpmanual.io/usage/models/#dynamic-model-creation) but it might be too complex if you just want to return some users. – Hernán Alarcón Sep 20 '21 at 23:27
  • @HernánAlarcón ahh, got it. i mean, i can obviously put it in the json format that i want without using a response model..for example: result[user_id] = {'user_name':user_name, 'user_pass':user_pass} | but, i figured it would be preferable using a well-known library? – avnav99 Sep 20 '21 at 23:51

1 Answers1

8

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.

alex_noname
  • 26,459
  • 5
  • 69
  • 86