错误 - 类型错误 DeclartativeMeta 对象为关键字参数“owner_id”获得了多个值

Posted

技术标签:

【中文标题】错误 - 类型错误 DeclartativeMeta 对象为关键字参数“owner_id”获得了多个值【英文标题】:Error - Type Error DeclartativeMeta object got multiple values for keyword argument 'owner_id' 【发布时间】:2022-01-24 01:50:24 【问题描述】:

我有一个问题,我用头撞桌子太久了,所以我要把它带到 ***。希望你们能帮助我! :)

虽然我知道错误非常具体,但我似乎无法理解它。我正在尝试创建一种如下关系:用户有一个帐户,一个帐户有很多交易。我仍然收到错误消息:

TypeError: DeclarativeMeta object got multiple values for keyword argument 'owner_id'

如果有人可以向我解释一下,那就太好了!

虽然我正在使用 Python、fastapi 和 sqlalchemy,但我确实认为我在使用 sqlalchemy 时犯了一个错误

我的模型.py


# User model
class User(_database.Base):
    __tablename__ = "users"
    id = _sql.Column(_sql.Integer, primary_key=True, index=True)
    email = _sql.Column(_sql.String, unique=True, index=True)
    hashed_password = _sql.Column(_sql.String)
    date_created = _sql.Column(_sql.DateTime, default=_dt.datetime.utcnow)

    accounts = _orm.relationship("Account", back_populates="owner")
    trades = _orm.relationship("Trade", back_populates="trades")

    # Function om te checken of het verzonden password matched met het hashed passowrd met bcrypt
    def verify_password(self, password: str):
        return _hash.bcrypt.verify(password, self.hashed_password)


# Account model
class Account(_database.Base):
    __tablename__ = "accounts"
    id = _sql.Column(_sql.Integer, primary_key=True, index=True)
    owner_id = _sql.Column(_sql.Integer, _sql.ForeignKey("users.id"))
    first_name = _sql.Column(_sql.String, index=True)
    last_name = _sql.Column(_sql.String, index=True)
    role = _sql.Column(_sql.String, index=True)
    note = _sql.Column(_sql.String, default="")
    date_created = _sql.Column(_sql.DateTime, default=_dt.datetime.utcnow)
    date_last_updated = _sql.Column(_sql.DateTime, default=_dt.datetime.utcnow)

    owner = _orm.relationship("User", back_populates="accounts")


# Trade Model
class Trade(_database.Base):
    __tablename__ = "trades"
    id = _sql.Column(_sql.Integer, primary_key=True, index=True)
    owner_id = _sql.Column(
        _sql.Integer, _sql.ForeignKey("users.id")
    )  # Krijgt een FK mee zodat een trade bij User kan komen
    trade_id = _sql.Column(
        _sql.Integer, index=True
    )  # Trades die gemaakt zijn hebben een uniek id vanuit exchange
    ticker = _sql.Column(
        _sql.String, index=True
    )  # Welke ticket is de trade gemaakt bv BTC/USDT, DOGE/USDT, etc.
    exchange = _sql.Column(
        _sql.String, index=True
    )  # Op welke exchange is de trade gemaakt
    date_created = _sql.Column(_sql.DateTime, default=_dt.datetime.utcnow)
    trade_note = _sql.Column(
        _sql.String, default=""
    )  # kunnen mensen toevoegen waarom ze een trade zijn ingestrap (Soort logboek)

    trades = _orm.relationship("User", back_populates="trades")

我的services.py(抛出错误的函数是create_trade(),是最后一个)


async def create_user(user: _schemas.UserCreate, db: _orm.Session):
    user_obj = _models.User(
        email=user.email, hashed_password=_hash.bcrypt.hash(user.hashed_password)
    )
    db.add(user_obj)
    db.commit()
    db.refresh(user_obj)
    return user_obj


async def authenticate_user(email: str, password: str, db: _orm.Session):
    user = await get_user_by_email(db=db, email=email)

    if not user:
        return False

    if not user.verify_password(password):
        return False

    return user


async def create_token(user: _models.User):
    user_obj = _schemas.User.from_orm(user)

    token = _jwt.encode(user_obj.dict(), JWT_SECRET)

    return dict(access_token=token, token_type="bearer")


async def get_current_user(
    db: _orm.Session = _fastapi.Depends(get_db),
    token: str = _fastapi.Depends(oauth2schema),
):
    try:
        payload = _jwt.decode(token, JWT_SECRET, algorithms=["HS256"])
        user = db.query(_models.User).get(payload["id"])
    except:
        raise _fastapi.HTTPException(
            status_code=401, detail="Invalid Email or Password"
        )

    return _schemas.User.from_orm(user)


async def create_trade(
    user: _schemas.User, db: _orm.Session, trade: _schemas.TradeCreate
):
    # **trade.dict() 'unpacked' als het waren de Trade model dus je kan zegegen
    # zelfde als het zeggen trade.owner_id = owner_id, trade.ticker = ticker, etc.

    trade = _models.Trade(**trade.dict(), owner_id=user.id)
    db.add(trade)
    db.commit()
    db.refresh(trade)

    print(f"user.id ================")

    return _schemas.Trade.from_orm(trade)


最后但并非最不重要的是我的 main.py

@app.post("/api/users")
async def create_user(
    user: _schemas.UserCreate, db: _orm.Session = _fastapi.Depends(_services.get_db)
):
    db_user = await _services.get_user_by_email(user.email, db)
    if db_user:
        raise _fastapi.HTTPException(status_code=400, detail="Email already exists")

    await _services.create_user(user, db)

    return await _services.create_token(user)


# Token om toegang te krijgen tot authenticated gedeelte


@app.post("/api/token")
async def generate_token(
    form_data: _security.OAuth2PasswordRequestForm = _fastapi.Depends(),
    db: _orm.Session = _fastapi.Depends(_services.get_db),
):
    # gebruikt email
    user = await _services.authenticate_user(form_data.username, form_data.password, db)

    if not user:
        raise _fastapi.HTTPException(status_code=401, detail="Invalid Credentials")

    return await _services.create_token(user)


# @param me - is als in de authenticated user, hier staat me dus voor
@app.get("/api/users/me", response_model=_schemas.User)
async def get_user(user: _schemas.User = _fastapi.Depends(_services.get_current_user)):
    return user


@app.post("/api/trades", response_model=_schemas.Trade)
async def create_trade(
    trade: _schemas.TradeCreate,
    user: _schemas.User = _fastapi.Depends(_services.get_current_user),
    db: _orm.Session = _fastapi.Depends(_services.get_db),
):
    return await _services.create_trade(user=user, db=db, trade=trade)

schema.py

class AccountCreate(_AccountBase):
    pass


class Account(_AccountBase):
    id: int
    owner_id: int
    date_created: _dt.datetime
    date_late_updated: _dt.datetime

    class Config:
        orm_mode = True


class _TradeBase(_pydantic.BaseModel):
    id: int
    owner_id: int
    trade_id: int
    ticker: str
    exchange: str
    date_created: _dt.datetime
    trade_note: str


# De twee functies hieronder vooralsnog (redundant wordt niks mee gedaan)
class Trade(_TradeBase):
    class Config:
        orm_mode = True

    pass


class TradeCreate(_TradeBase):
    pass

欢迎所有提示和技巧!谢谢!

【问题讨论】:

请添加您的 TradeCreate 架构代码。 哎呀,这不是我最聪明的举动!加了! @kosciej16 您现在添加了两次models.py,仍然没有TradeCreate;/ 更正啊……这不是我最聪明的时刻。感谢您的耐心:8 @kosciej16 你应该习惯这一点,我们的大多数编程试验都不是最聪明的;) 【参考方案1】:

我就是这么想的,看这里:

trade = _models.Trade(**trade.dict(), owner_id=user.id)

请注意,trade 已经有owner_id 字段。这意味着您尝试通过它两次。您一定认为您是否需要owner_id 进行交易。如果是这样,您需要从那里删除一个owner_id

trade = _models.Trade(**trade.dict())

或exclude

trade = _models.Trade(**trade.dict(exclude="owner_id"), owner_id=user.id)

【讨论】:

啊!!!非常感谢您的解释!我确实认为我希望拥有 owner_id,因为我希望能够找到特定用户的交易(然后将它们显示给用户)。这是一个很好的解决方案还是你会用另一种方式来做?再次感谢您的帮助,它就像一个魅力! 我的意思是您可以从 TradeCreate 架构中删除 owner_id,因为您无论如何都不使用它。因此,在您的具体情况下,将 owner_id_TradeBase 移动到 Trade 实际上同样适用于 id - 在将 id 插入数据库之前,您怎么可能知道它?您当然可以在前端跟踪 id,但让 db 为 id 分配一些序列(或 uuid)并在需要时返回它作为响应会更有效。 + trade_id/id 乍一看似乎是多余的

以上是关于错误 - 类型错误 DeclartativeMeta 对象为关键字参数“owner_id”获得了多个值的主要内容,如果未能解决你的问题,请参考以下文章

js常见错误类型

错题本上的常见错误类型及改正方法

js错误类型

我收到错误错误类型参数一元减号和预期';'在 ':' 标记之前

javascript错误信息

ASP.NET MVC前台解析JSON时,类型错误