簡體   English   中英

更新 SQLAlchemy ORM 現有的 model 從發布的 Pydantic Z20F35E630DAF44DBFA4C3F688C

[英]Update SQLAlchemy ORM existing model from posted Pydantic model in FastAPI?

我想公開一個 API 方法,該方法在 POST 請求中接收數據(用於 beta 注冊 API),並在已經有匹配的 model 時使用新值進行更新。 實現這一目標的最佳方法是什么? 目前我正在這樣做(有點簡化):

我的 ORM model(SqlAlchemy):

class BetaORM(Base):
    __tablename__ = "betasignup"
    email = Column(EmailType, primary_key=True)
    fullname = Column(String, unique=False, index=False, nullable=True)

我的 Pydantic model:

class BetaCreate(BaseModel):
    email: EmailStr
    fullname: Optional[str]

我的 FastAPI 發布方法:

@app.post("/beta_signup")
def post_beta_signup(beta: schemas.BetaCreate, db: Session = Depends(get_db)):
    return create_beta_signup(db=db,signup=beta)

還有我寫的 CRUD 方法:

def create_beta_signup(db: Session, signup: schemas.BetaCreate):
    db_beta = schemas.BetaORM(**signup.dict())
    ret_obj = db.merge(db_beta)
    db.add(ret_obj)
    db.commit()
    return ret_obj

使用 merge() 的一個問題是它依賴於與主鍵匹配,直接針對 email 地址 - 我寧願使用代理鍵,這樣我就可以擁有禁用/刪除功能而不是被迫擁有在數據庫級別對 email 地址的唯一約束。

基於FastAPI sqlalchemy 演示應用程序,這是解決此問題的方法:

def update_user(db: Session, user: PydanticUserUpdate):
    """
    Using a new update method seen in FastAPI https://github.com/tiangolo/fastapi/pull/2665
    Simple, does not need each attribute to be updated individually
    Uses python in built functionality... preferred to the pydintic related method
    """

    # get the existing data
    db_user = db.query(User).filter(User.id == user.id).one_or_none()
    if db_user is None:
        return None

    # Update model class variable from requested fields 
    for var, value in vars(user).items():
        setattr(db_user, var, value) if value else None

    db_user.modified = modified_now
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user

此方法使用 SQLAlchemy 聲明性 model 定義(不是 Gabriel Cappelli 使用的命令式定義)

完整的源代碼

我使用這種方法在基於 FastAPI 的應用程序中進行 crud 更新。 現有數據保持不變,並覆蓋新的更新值。 修改后的日期時間已更新(但為了便於測試,此值是固定的)。

希望能幫助到你。 (我花了太長時間才弄清楚這一點。)

如果您使用 MySQL 和 SQLAlchemy >= 1.2,您可以使用INSERT...ON DUPLICATE KEY UPDATE使用 SQLAlchemy。

from sqlalchemy.dialects.mysql import insert

insert_stmt = insert(my_table).values(
    id='some_existing_id',
    data='inserted value')

on_duplicate_key_stmt = insert_stmt.on_duplicate_key_update(
    data=insert_stmt.inserted.data,
    status='U'
)

conn.execute(on_duplicate_key_stmt)

有關文檔的更多信息

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM