В fastapi эндпоинте работает redis.set, но не работает redis.incr

Написал код для работы с fastapi и redis:

from fastapi import APIRouter, UploadFile, File, HTTPException, Depends
from sqlalchemy import select
from Auth.manager import current_user
from Pins.services import upload_file, file_validator
from Pins.models import Pin, Tag
from database import async_session_maker as async_session, User
import redis

redis_client = redis.Redis(host="localhost", port=6379, db=0)

router = APIRouter()

@router.post("/createpin")
async def pin_create(title: str, desc: str, file: UploadFile = File(...), user: User = Depends(current_user)):

    if not file_validator(file):
        return HTTPException(status_code=418, detail="File not a video or image or file size > 200MB")

    await upload_file(file)

    async with async_session() as session:
        new_pin = Pin(title=title, desc=desc, file=file.filename, creator=user.id)
        session.add(new_pin)
        await session.flush()

        redis_client.set(f"{new_pin.id}", 1)
        await session.commit()
    return {"file": file.filename, "creator": user}

@router.get("/")
async def pins_list():
    async with async_session() as session:
        result = await session.execute(select(Pin))
        pins = result.scalars().all()
    return pins

@router.get("/{user}")
async def pins_list_by_user(user: int):
    async with async_session() as session:
        result = select(Pin).where(Pin.creator == user)
        users_pins = await session.execute(result)
    return users_pins.scalars().all()

@router.get("/{pin}")
async def retrieve_pin(pin: int):
    views = redis_client.incr(f"{pin}")

    async with async_session() as session:
        result = select(Pin).where(Pin.id == pin)
        pinn = await session.execute(result)

    return {"views": views, "pin": pinn.scalars().one()}

Endpoint pin_create отрабатывает верно, а retrieve_pin выводит данные, но incr не отрабатывает. Не понимаю - почему?


Ответы (1 шт):

Автор решения: AnnaBazueva

FastAPI – Параметры пути

В FastAPI, когда вы определяете маршруты с параметрами, они должны быть уникальными.

В вашем случае у вас есть два маршрута с "одинаковым" путем:

  1. @router.get("/{user}")
  2. @router.get("/{pin}")
    (если передать одинаковые параметры, то пути будут равными!
    т.к. оба параметра имеют тип int,
    {user} == 13 & {pin} == 13 сформируют одинаковый путь localhpst:8000/13
    что может привести к тому, что FastAPI не сможет правильно сопоставить запросы с нужным маршрутом. )

Сделайте пути уникальными:

@router.get("/user/{user}")
async def pins_list_by_user(user: int):
    # Далее ваш код...

@router.get("/pin/{pin}")
async def retrieve_pin(pin: int):
    # Далее ваш код...
→ Ссылка