У меня есть структура из 3 таблиц
- users
- userFields (ссылается m2o на users, ссылается o2o на userFieldTypes)
- userFieldTypes
Хочу на стороне fastapi получать и отдавать users сразу с его доп полями, и уже внутри по sql распихивать как мне удобно.
Я сделал так, чтобы pydantic модель User можно было менять, вот мои модели для view стороны
class UserFieldType(BaseModel):  # create and update
    id: Optional[int]
    name: str
    type: str
    @field_validator('type')
    @classmethod
    def validate_type(cls, value):
        if value not in ALLOWED_USER_FIELD_TYPE:
            raise ValidationError(f'type must be one of {list(ALLOWED_USER_FIELD_TYPE.keys())}')
        return value
class User(BaseModel):
    id: Optional[int]
    login: str
    password: str
    description: Optional[str]
    # dynamic extra fields
    @classmethod
    def add_field(cls, name: str, definition: Any, default: Any = ..., optional=True):
        if name in cls.model_fields:
            raise ValueError(f"Field {name} already exist")
        cls.change_field(name, Optional[definition], default, optional)
    @classmethod
    def change_field(cls, name: str, definition: Any, default: Any = None, optional=True):
        if optional:
            definition=Optional[definition]
        new_field = FieldInfo(annotation=definition, default=default)
        cls.model_fields.update({name: new_field})
        cls.model_rebuild(force=True)
    @classmethod
    def delete_field(cls, name: str):
        cls.model_fields.pop(name)
        cls.model_rebuild(force=True)
И для проверки этого всего сделал несколько маршрутов
@router.get("/users", response_model=(List[schemas.view.User]))
def get_users(
        db_session: Session = Depends(session.get_session)
):
    return db_session.query(models.User).all()
@router.post("/users", response_model=schemas.view.User)
def add_user(
        user: schemas.view.User,
        db_session: Session = Depends(session.get_session)
):
    print(user)
    print('tst' in user)
    print(user.tst if 'tst' in user else "")
    print(schemas.view.User.model_fields)
    return user
@router.get("/user/extra_fields", response_model=(List[schemas.db.UserFieldType]))
def get_user_extra_fields(
        db_session: Session = Depends(session.get_session)
):
    return db_session.query(models.UserFieldType).all()
@router.post("/user/extra_fields", response_model=schemas.db.UserFieldType)
def add_user_extra_field(
        field: schemas.view.UserFieldType,
        db_session: Session = Depends(session.get_session)
):
    new_field = models.UserFieldType(**field.model_dump())
    print(schemas.view.User.model_fields)
    schemas.view.User.add_field(field.name, ALLOWED_USER_FIELD_TYPE[field.type])
    db_session.add(new_field)
    db_session.commit()
    print(schemas.view.User.model_fields)
    from app.main import app
    app.openapi_schema = None
    app.setup()
    return new_field
Проблема 1:
Я ожидал, что с изменением модели openapi схему надо будет пнуть и для этого у меня app.setup(), но документация в http:/.../docs' не обновляется.
Проблема 2:
Даже с учётом того, что я изменил модель User (добавив поле tst) fastapi её не подхватывает,
т.е. запрос к post("/users") с данными '{"id": 1, "login": "l1", "password": "p1", "description": "d1", "tst": "t1"}' выполняется, но в полученном объекте нет поля tst, эти данные потеряны. А именно я вижу:
- print('tst' in user)->- False
- print(schemas.view.User.model_fields)-> вижу своё новое поле- {'id': FieldInfo(annotation=Union[int, NoneType], required=True), 'login': FieldInfo(annotation=str, required=True), 'password': FieldInfo(annotation=str, required=True), 'description': FieldInfo(annotation=Union[str, NoneType], required=True), 'tst': FieldInfo(annotation=Union[str, NoneType], required=True)}
Вопрос, что надо правильно пнуть в fastapi чтобы хотябы пройти проблему №2 ?

