【问题标题】:Getting error TypeError: 'SQLModelMetaclass' object is not iterable出现错误 TypeError: \'SQLModelMetaclass\' object is not iterable
【发布时间】:2022-08-18 17:00:47
【问题描述】:

我有一个使用具有 JWT 身份验证活动的 SQLModel 的 fastapi 项目。我有一个注册端点,并试图在向注册端点发布成功时返回用户记录的子集。我似乎能够返回绑定到实际表的 \'User\' 模型,但我不想返回密码哈希,所以我创建了一个名为 \'SensitiveUser\' 的新模型,它不绑定到任何表删除密码。但是,当我尝试使用此模型并从端点返回数据时,我收到错误 \"TypeError: \'SQLModelMetaclass\' object is not iterable\"。任何关于为什么会发生这种情况的见解都值得赞赏。我正在努力在网上其他地方找到这个确切的问题。谢谢。

回购:

# Return all users.
def select_all_users():
    with Session(rms_engine) as session:
        statement = select(User)
        res = session.exec(statement).all()
        return res

# Returns a specific user record.
def find_user(name):
    with Session(rms_engine) as session:
        statement = select(User).where(User.username == name)
        return session.exec(statement).first()

# Returns a specific user record withou password information.
def find_sensitive_user(name):
    with Session(rms_engine) as session:
        statement = select(SensitiveUser).where(SensitiveUser.username == name)
        return session.exec(statement).first()

楷模:

class User(SQLModel, table=True):
    id: Optional[int] = Field(primary_key=True)
    username: str
    password: str = Field(max_length=256, min_length=6)
    email: EmailStr
    created_at: datetime.datetime = datetime.datetime.now()
    is_admin: bool = False

class SensitiveUser(SQLModel):
    id: int
    username: str
    email: str
    created_at: datetime.datetime

下面的代码确实有效,但返回的信息比我想要的多,即密码:

@user_router.post(\'/register\', status_code=201, tags=[\'users\'], description=\'Register a new user\')
def register(user: UserInput):
    users = select_all_users()
    if any(x.username == user.username for x in users):
        raise HTTPException(status_code=400, detail=\'Username is taken\')
    hashed_pwd = auth_handler.get_password_hash(user.password)
    u = User(username=user.username, password=hashed_pwd, email=user.email, is_admin=user.is_admin)
    rms_session.add(u)
    rms_session.commit()
    stored_user = find_user(user.username) 
    return stored_user

下面的代码返回 \"TypeError: \'SQLModelMetaclass\' object is not iterable\" 错误:

@user_router.post(\'/register\', status_code=201, tags=[\'users\'], description=\'Register a new user\')
def register(user: UserInput):
    users = select_all_users()
    if any(x.username == user.username for x in users):
        raise HTTPException(status_code=400, detail=\'Username is taken\')
    hashed_pwd = auth_handler.get_password_hash(user.password)
    u = User(username=user.username, password=hashed_pwd, email=user.email, is_admin=user.is_admin)
    rms_session.add(u)
    rms_session.commit()
    stored_user = find_sensitive_user(user.username) # <--- Error Occurs Here
    return stored_user
  • JSON 编码器可能需要遍历您返回的对象(SQLModelMetaclass),这会导致错误。尝试将结果转换为dict

标签: python fastapi sqlmodel


【解决方案1】:

问题是您无法选择尚未映射到数据库表的对象,而 SensitiveUser 的对象则不是! 您应该扩展您的 User 类以生成 SensitiveUsers,如下所示:

class User(SQLModel, table=True):
    id: Optional[int] = Field(primary_key=True)
    username: str
    password: str = Field(max_length=256, min_length=6)
    email: str
    created_at: datetime.datetime = datetime.datetime.now()
    is_admin: bool = False

    def to_sensitive_user(self) -> SensitiveUser:
        return SensitiveUser(id=self.id, username=self.username, 
                             email=self.email, created_at=self.created_at)

然后,您可以使用通过调用to_sensitive_user() 扩展的find_user 函数,如下所示:

stored_user = find_user(user.username).to_sensitive_user()

当然这里需要一些 is-not-None 检查并且SensitiveUser 也需要在User 之前定义。

【讨论】:

    猜你喜欢
    • 2022-12-15
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    • 2018-02-01
    • 1970-01-01
    • 2021-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多