Fastapi(Starlette)重定向到POST而不是GET方法 [英] fastapi (starlette) RedirectResponse redirect to post instead get method

查看:0
本文介绍了Fastapi(Starlette)重定向到POST而不是GET方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在返回RedirectResponse对象后遇到奇怪的重定向行为

events.py

router = APIRouter()

@router.post('/create', response_model=EventBase)
async def event_create(
        request: Request,
        user_id: str = Depends(get_current_user),
        service: EventsService = Depends(),
        form: EventForm = Depends(EventForm.as_form)
):
    event = await service.post(
       ...
   )
    redirect_url = request.url_for('get_event', **{'pk': event['id']})
    return RedirectResponse(redirect_url)


@router.get('/{pk}', response_model=EventSingle)
async def get_event(
        request: Request,
        pk: int,
        service: EventsService = Depends()
):
    ....some logic....
    return templates.TemplateResponse(
        'event.html',
        context=
        {
            ...
        }
    )

routers.py

api_router = APIRouter()

...
api_router.include_router(events.router, prefix="/event")

此代码返回结果

127.0.0.1:37772 - "POST /event/22 HTTP/1.1" 405 Method Not Allowed
好的,我看到出于某种原因,调用的是POST请求,而不是GET请求。我搜索解释,发现ReDirectResponse对象默认为代码307,并调用POSTlink

我按照建议添加状态

redirect_url = request.url_for('get_event', **{'pk': event['id']}, status_code=status.HTTP_302_FOUND)

并获取

starlette.routing.NoMatchFound

对于实验,我将@router.get('/{pk}', response_model=EventSingle)更改为@router.post('/{pk}', response_model=EventSingle)

并且重定向成功完成,但是POST请求不适合我这里。我做错了什么?

更新

用于运行事件/创建逻辑的html表单

base.html

<form action="{{ url_for('event_create')}}" method="POST">
...
</form>

base_view.py

@router.get('/', response_class=HTMLResponse)
async def main_page(request: Request,
                    activity_service: ActivityService = Depends()):
    activity = await activity_service.get()
    return templates.TemplateResponse('base.html', context={'request': request,
                                                            'activities': activity})

推荐答案

当您想要在发布后重定向到GET时,最佳做法是to redirect with a 303 status code,因此只需将代码更新为:

    # ...
    return RedirectResponse(redirect_url, status_code=303)

如您所见,redirecting with 307 keeps the HTTP method and body

完整工作示例:

from fastapi import FastAPI, APIRouter, Request
from fastapi.responses import RedirectResponse, HTMLResponse


router = APIRouter()

@router.get('/form')
def form():
    return HTMLResponse("""
    <html>
    <form action="/event/create" method="POST">
    <button>Send request</button>
    </form>
    </html>
    """)

@router.post('/create')
async def event_create(
        request: Request
):
    event = {"id": 123}
    redirect_url = request.url_for('get_event', **{'pk': event['id']})
    return RedirectResponse(redirect_url, status_code=303)


@router.get('/{pk}')
async def get_event(
        request: Request,
        pk: int,
):
    return f'<html>oi pk={pk}</html>'

app = FastAPI(title='Test API')

app.include_router(router, prefix="/event")

若要运行,请安装pip install fastapi uvicorn并使用:

运行
uvicorn --reload --host 0.0.0.0 --port 3000 example:app
然后,将您的浏览器指向:http://localhost:3000/event/form

这篇关于Fastapi(Starlette)重定向到POST而不是GET方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆