如何在 FastAPI 中将 RedirectResponse 从 POST 发送到 GET 路由?

Pri*_*nha 5 fastapi

我想使用从 发送数据app.post()到。app.get()RedirectResponse

@app.get('/', response_class=HTMLResponse, name='homepage')
async def get_main_data(request: Request,
                        msg: Optional[str] = None,
                        result: Optional[str] = None):
    if msg:
        response = templates.TemplateResponse('home.html', {'request': request, 'msg': msg})
    elif result:
        response = templates.TemplateResponse('home.html', {'request': request, 'result': result})
    else:
        response = templates.TemplateResponse('home.html', {'request': request})
    return response
Run Code Online (Sandbox Code Playgroud)
@app.post('/', response_model=FormData, name='homepage_post')
async def post_main_data(request: Request,
                         file: FormData = Depends(FormData.as_form)):
       if condition:
        ......
        ......

        return RedirectResponse(request.url_for('homepage', **{'result': str(trans)}), status_code=status.HTTP_302_FOUND)

    return RedirectResponse(request.url_for('homepage', **{'msg': str(err)}), status_code=status.HTTP_302_FOUND)
Run Code Online (Sandbox Code Playgroud)
  1. 我如何发送resultmsg通过RedirectResponse,url_for()app.get()
  2. 有没有办法将 URL 中的数据隐藏为path parameterquery parameter?我该如何实现这一目标?

starlette.routing.NoMatchFound: No route exists for name "homepage" and params "result".我在尝试这种方法时遇到错误。

更新:

我尝试了以下方法:

return RedirectResponse(app.url_path_for(name='homepage')
                                + '?result=' + str(trans),
                                status_code=status.HTTP_303_SEE_OTHER)
Run Code Online (Sandbox Code Playgroud)

上面的代码可以工作,但它是通过将参数作为query参数发送来工作的,即 URL 看起来像这样localhost:8000/?result=hello。有没有办法做同样的事情但不显示在 URL 中?

Chr*_*ris 2

对于从方法重定向POSTGET方法,请查看答案,了解如何执行此操作以及使用原因status_code=status.HTTP_303_SEE_OTHER(示例如下)。

至于报错的原因starlette.routing.NoMatchFound,这是因为request.url_for()接收path参数,而不是 query参数。你的msgresult参数是query一个;因此,出现错误。

解决方案是使用 a CustomURLProcessor,如答案和答案中所建议的那样,允许您将path(如果需要)和query参数传递给url_for()函数并获取 URL。至于隐藏URL 中的path和/或参数,您可以使用与此答案类似的方法,即使用(或) 替换浏览器地址栏中的 URL。queryhistory.pushState()history.replaceState()

完整的工作示例可以在下面找到(您可以使用自己的示例TemplateResponse代替HTMLResponse)。

from fastapi import FastAPI, Request, status
from fastapi.responses import RedirectResponse, HTMLResponse
from typing import Optional
import urllib

app = FastAPI()

class CustomURLProcessor:
    def __init__(self):  
        self.path = "" 
        self.request = None

    def url_for(self, request: Request, name: str, **params: str):
        self.path = request.url_for(name, **params)
        self.request = request
        return self
    
    def include_query_params(self, **params: str):
        parsed = list(urllib.parse.urlparse(self.path))
        parsed[4] = urllib.parse.urlencode(params)
        return urllib.parse.urlunparse(parsed)
        

@app.get('/', response_class=HTMLResponse)
def event_msg(request: Request, msg: Optional[str] = None):
    if msg:
        html_content = """
        <html>
           <head>
              <script>
                 window.history.pushState('', '', "/");
              </script>
           </head>
           <body>
              <h1>""" + msg + """</h1>
           </body>
        </html>
        """
        return HTMLResponse(content=html_content, status_code=200)
    else:
        html_content = """
        <html>
           <body>
              <h1>Create an event</h1>
              <form method="POST" action="/">
                 <input type="submit" value="Create Event">
              </form>
           </body>
        </html>
        """
        return HTMLResponse(content=html_content, status_code=200)

@app.post('/')
def event_create(request: Request):
    redirect_url = CustomURLProcessor().url_for(request, 'event_msg').include_query_params(msg="Succesfully created!")
    return RedirectResponse(redirect_url, status_code=status.HTTP_303_SEE_OTHER)
Run Code Online (Sandbox Code Playgroud)

更新 1 - 关于包含查询参数

关于向url_for()函数添加查询参数,另一个解决方案是使用 Starlette 的starlette.datastructures.URL,它现在提供了一种include_query_params. 例子:

from starlette.datastructures import URL

redirect_url = URL(request.url_for('event_msg')).include_query_params(msg="Succesfully created!")
Run Code Online (Sandbox Code Playgroud)

更新 2 - 关于包含查询参数

request.url_for()函数现在返回一个starlette.datastructures.URL对象。因此,您可以按如下方式添加查询参数:

redirect_url = request.url_for('event_msg').include_query_params(msg="Succesfully created!")
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

10459 次

最近记录:

1 年,11 月 前