这不是 FastAPI 的问题,而是斯塔莱特的 https://github.com/tiangolo/fastapi/issues/323#issuecomment-506837279问题(即request.url_for()
收到path
参数,not query
参数)。所以,受到启发#560 https://github.com/encode/starlette/issues/560#issuecomment-769622920 and #1385 https://github.com/encode/starlette/pull/1385,我创建了以下工作示例,用于从 Jinja2 模板中调用 FastAPI 路由,并传递query
params(单独或与path
参数也是如此)。
请注意,该功能可能会在 Starlette 的下一版本中引入#1385 https://github.com/encode/starlette/pull/1385。因此,最好在它出来时使用它。
app.py
import uvicorn
from fastapi import FastAPI, Response
from fastapi.templating import Jinja2Templates
from fastapi import Request
from fastapi.responses import HTMLResponse
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)
templates = Jinja2Templates(directory='templates')
templates.env.globals['CustomURLProcessor'] = CustomURLProcessor
@app.get('/updates/page/{page_no}/item/{item_id}')
def updates(request: Request, page_no: int, item_id: int, user: str, msg: str):
return templates.TemplateResponse("item.html", {"request": request, "page_no": page_no, "item_id":item_id, "user": user, "msg": msg})
@app.get('/updates_query_only')
def updates_query_only(request: Request, user: str, msg: str):
return templates.TemplateResponse("item.html", {"request": request, "user": user, "msg": msg})
@app.get('/')
def index(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
if __name__ == '__main__':
uvicorn.run(app, host='127.0.0.1', port=8000, debug=True)
模板/索引.html
<!DOCTYPE html>
<html>
<body>
<div class="container">
{% set cu = CustomURLProcessor() %}
{% set _url = cu.url_for(request, 'updates', page_no=5, item_id=3).include_query_params(user='foo', msg='bar') %}
<!-- if only query params required, use as follows: -->
{# {% set _url = cu.url_for(request, 'updates_query_only').include_query_params(user='foo', msg='bar') %} #}
<iframe src="{{ _url }}" width = 300 height = 300 style= "border: none;"></iframe>
</div>
</body>
</html>
模板/项目.html
<!DOCTYPE html>
<html>
<body>
<h1>Page No {{ page_no }}</h1>
<h2>Item {{ item_id }}</h2>
<h3>{{ user }}</h3>
<h4>{{ msg }}</h4>
</body>
</html>
Update
您现在可以使用 Starlette 的starlette.datastructures.URL https://github.com/encode/starlette/blob/5006a304fab65c114f649c16c8d3aa12cbf37c6b/starlette/datastructures.py#L23,它提供了一种方法include_query_params https://github.com/encode/starlette/blob/5006a304fab65c114f649c16c8d3aa12cbf37c6b/starlette/datastructures.py#L136。下面的例子:
In app.py导入URL
类并使其可从 Jinja2 模板访问:
from starlette.datastructures import URL
templates = Jinja2Templates(directory="templates")
templates.env.globals['URL'] = URL
在模板/项目.html使用方法如下:
<!DOCTYPE html>
<html>
<body>
<div class="container">
<iframe src="{{ URL(url_for('updates', page_no=5, item_id=3)).include_query_params(user='foo', msg='bar') }}" width = 300 height = 300 style= "border: none;"></iframe>
</div>
</body>
</html>