我想使用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
@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)
app.get()
RedirectResponse
、url_for()
将result
或msg
发送到URL中,以path parameter
或query 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)
上面的方法是工作的,但它的工作方式是将param发送为query
param,也就是说,localhost:8000/?result=hello
看起来类似于这个localhost:8000/?result=hello
。有没有办法做同样的事情,但不显示在URL中?
发布于 2022-07-23 07:23:33
对于从POST
重定向到GET
方法,请看一下this和this的答案,说明如何做到这一点,以及使用status_code=status.HTTP_303_SEE_OTHER
的原因(下面给出示例)。
至于获取starlette.routing.NoMatchFound
错误的原因,这是因为request.url_for()
接收path
参数,而不是 query
参数。您的msg
和result
参数是query
参数,因此出现了错误。
解决方案是使用CustomURLProcessor
,如this和this应答中所建议的那样,允许您将path
(如果需要)和query
参数传递给url_for()
函数并获得URL。至于将path
和/或query
参数隐藏在URL中,您可以使用与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)
更新
关于向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!")
return RedirectResponse(redirect_url, status_code=status.HTTP_303_SEE_OTHER)
https://stackoverflow.com/questions/73076517
复制相似问题