SqlAlchemy пример обновления записи в базе данных ORM методом update()

Практически любой проект состоит из базы данных и информации содержащейся в ней. Вся ценность информации в ее полезности и актуальности. Для актуализации информации ее а) для начала нужно добавить, б) периодически нужно актуализировать. Об этом мы сегодня и поговорим но в контексте определенного стека а именно SqlAlchemy, FastApi, Pydantic.

Итак допустим у нас есть таблица в базе данных Postgresql.

import uuid

from sqlalchemy import Column, String, Boolean, Integer, ARRAY, ForeignKey
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.types import Date
from sqlalchemy.orm import relationship
from app.database.base import Base
from app.models.mixins import TimestampMixin


class User(TimestampMixin, Base):
    __tablename__ = "users"
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
    first_name = Column(String, index=True)
    last_name = Column(String, nullable=False, index=True, comment="Фамилия") 
    patronymic = Column(String, nullable=True, index=True, comment="Отчество")
    email = Column(String, unique=True, index=True, nullable=False)
    phone = Column(String, unique=True, index=True, nullable=False)

А также есть соответствующая Pydantic схема для определения полей. Схемы у меня асбтрактные бездумно копироать не стоит привел для построения целостной картины.

from pydantic import BaseModel, EmailStr, UUID4, Field, validator

class UserBase(BaseModel):
    first_name: Optional[str] = None
    last_name: Optional[str] = None
    patronymic: Optional[str] = None
    email: Optional[EmailStr] = None
    phone: Optional[str] = None

# Properties to receive via API on creation
class UserCreate(UserBase):
    email: EmailStr
    first_name: str
    last_name: str 
    password: str

class UserOut(BaseModel):
    id: Optional[UUID4]
    clinic_id: Optional[UUID4]
    clinic: Optional[ClinicResponse]
    email: Optional[EmailStr]
    first_name: Optional[str]
    last_name: Optional[str]
    patronymic: Optional[str]

    class Config:
        orm_mode = True

Далее у нас идет сам роут по которому мы будем получать запросы.

import os, random
from typing import List
import uuid
from uuid import uuid4
from fastapi import APIRouter, HTTPException, status, Depends, UploadFile, File
from fastapi.responses import JSONResponse
from sqlalchemy.ext.asyncio import AsyncSession
from fastapi_pagination import Page
from fastapi_pagination.ext.async_sqlalchemy import paginate

from app.api.deps import get_current_active_user, get_session
from app.schemas.user import UserUpdate, UserAuth, UserOut, \
    UserListOut, UserCreate, PersonCreate, PersonOut
from app.core import security
from app import crud
from app.crud.crud_user import create_user as create_person, update_user as update_user_db
from app.core.config import settings
from app.S3_utils import get_s3_client, upload_file_to_bucket
from app.models.user import User as UserModel

router = APIRouter(prefix="/users", tags=["Аккаунты пользователей"])

@router.post("/update", summary="Обновление данных пользователя", response_model=PersonOut)
async def update_user(
    db: AsyncSession = Depends(get_session),
    current_user: UserOut = Depends(get_current_active_user),
    user_in: UserUpdate = None
    )-> PersonOut:
    user = await update_user_db(db=db, user_in=user_in)
    if user is None:
        raise HTTPException(
        status_code=status.HTTP_400_BAD_REQUEST,
        detail="Ошибка обновления данных"
    )
    return user

Ну и последний самый главный наш блок непосрредственно crud_user.py файл в котором и будет происходить работа с базой посредством orm — sqlalchemy, прекрасной библиотекой мощью которой я не перестаю удивляться.

import logging
from sqlalchemy import select, column
from typing import Any, Dict, Optional, Union
from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from fastapi.encoders import jsonable_encoder
from pydantic import UUID4

from app.crud.base import CRUDBase
from app.models.user import User
from app.models.clinic import Clinic
from app.schemas.user import UserCreate, UserUpdate, PersonCreate
from app.core import security
from fastapi_pagination.ext.async_sqlalchemy import paginate

async def update_user(db: AsyncSession, user_in: UserUpdate):
    stmt = (
        update(User).
        where(User.id == user_in.id).
        values(user_in.dict(exclude_unset=True)).
        returning(User)
    )
    result = await db.execute(stmt)
    await db.commit()
    # logging.info(result.first())
    return result.first()

Вот так вот просто и эффективно можно обновить запись в базе при помощи sqlalchemy, причем обратите внимание в моем примере асинхронная sqlalchemy в случае обычных синхронных сессий все будет тоже самое, только не будет async/await. Ну и еще бы хотел обратить вниманием на строчку

values(user_in.dict(exclude_unset=True)).

Тут мы модель Pydantic передаем непосредственно в sqllachemy таким образом полностью раскрываю мощь Pydantic по валидации данных.

Вам также может понравиться

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Яндекс.Метрика