【问题标题】:How to send RedirectResponse from a POST to a GET route in FastAPI?如何将数据从 POST 发送到 FastAPI 中的 GET 路由?
【发布时间】:2022-08-09 20:14:05
【问题描述】:

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

@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
@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)
  1. 如何通过RedirectResponseurl_forapp.get() 发送resultmsg
  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)
    
    

    这可行,但通过将参数发送为query 参数来实现,即,URL 看起来像这样localhost:8000/?result=hello。有没有办法做同样的事情,但没有在 URL 中显示?

  • 请查看答案herehere(您应该使用request.url_for() 中的方法名称,即get_main_data)。至于隐藏URL中的数据,请看this answer
  • 我试过了。在这两种情况下,我都会遇到相同的错误。也使用router。也尝试了get_main_data,结果相同

标签: fastapi


【解决方案1】:

对于从POST 重定向到GET 方法,请查看thisthis 答案,了解如何执行此操作以及使用status_code=status.HTTP_303_SEE_OTHER 的原因。

至于得到starlette.routing.NoMatchFound错误的原因,这是因为request.url_for()接收到path参数,不是query 参数。你的msgresult 参数是query 的;因此,错误。

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

完整的工作示例可以在下面找到(您可以使用自己的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)

【讨论】:

  • 谢谢回复。是的,我尝试了类似的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-09
  • 1970-01-01
  • 2023-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多