我不知道是否可以将查询参数从静态 html 页面传递到视图进行处理。我现在已经使用路径参数实现了我需要的功能。我想做同样的事情,但是带有查询参数
main.py
from helpers.utils import CustomURLProcessor
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")
templates.env.globals['CustomURLProcessor'] = CustomURLProcessor
事件.py
router = APIRouter()
templates = Jinja2Templates(directory="templates")
@router.post('/invite/{event_invite}/sender/{sender}')
async def decline_event_invite(
request: Request,
event_invite: int,
sender: int,
):
#logic
routes.py
api_router.include_router(events.router, prefix="/event")
html
{{ url_for('decline_event_invite', event_invite=invite.id, sender=invite.sender) }}
它可以与
"POST /event/invite/15/sender/3 HTTP/1.1"
作为示例
尝试使用查询参数
@router.post('/invite')
async def decline_event_invite(
request: Request,
event_invite: Optional[str] = None,
sender: Optional[str] = None,
):
# logic
并得到
raise NoMatchFound()
starlette.routing.NoMatchFound
html模板没有任何改变
我可以将查询参数从模板传递到fastapi逻辑来处理这个url吗
/event/?event_invite=15&sender=3
?
这是Starlette 的问题(即
url_for()
接收path
参数,不是query
参数)。您可以做的是创建一个自定义 URL 处理器(如下所示)并使用它来传递 path
和/或 query
参数。
import urllib
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)
记住将
CustomURLProcessor
类添加到模板的全局环境中:
templates.env.globals['CustomURLProcessor'] = CustomURLProcessor
然后在Jinja模板中使用,如下:
{{ CustomURLProcessor().url_for(request, 'decline_event_invite').include_query_params(event_invite=invite.id, sender=invite.sender) }}
请查看此答案以获取完整的工作示例。此外,该功能可能会被引入到 Starlette 的下一版本#1385中。因此,您可能需要密切关注。
使
CustomURLProcessor
类可从 Jinja 模板访问的替代选项,以防 templates.env.globals['CustomURLProcessor'] = CustomURLProcessor
不适合您,并抛出以下错误:jinja2.exceptions.UndefinedError: 'CustomURLProcessor' is undefined
。
选项1
templates.env.globals.update(CustomURLProcessor=CustomURLProcessor)
选项2
import helpers.utils
templates.env.globals['CustomURLProcessor'] = helpers.utils.CustomURLProcessor
# or, equivalently
templates.env.globals.update(CustomURLProcessor=helpers.utils.CustomURLProcessor)
您甚至可以添加整个模块,并在 Jinja 模板中使用,如下所示
helpers.CustomURLProcessor().url_for(request...
。
import helpers.utils
templates.env.globals['helpers'] = helpers.utils
选项3
最后一个选项是将其作为您的
TemplateResponse
的一部分传递。
return templates.TemplateResponse("index.html", {"request": request, "CustomURLProcessor": CustomURLProcessor})
如果上述方法均不起作用,也许此处描述的其他选项可能会有所帮助,或者问题可能出在其他地方。
关于从 Jinja 模板发送查询参数,您现在可以使用 Starlette 的
starlette.datastructures.URL
,它提供了 include_query_params
方法。
要使用,请导入
URL
类并使其可从 Jinja2 模板访问:
from starlette.datastructures import URL
templates = Jinja2Templates(directory="templates")
templates.env.globals['URL'] = URL
然后,在 Jinja 模板中使用,如下所示:
{{ URL(url_for('decline_event_invite')).include_query_params(event_invite=invite.id, sender=invite.sender) }}
request.url_for()
函数现在返回一个starlette.datastructures.URL
对象。因此,您可以简单地使用以下内容,而不需要在 Jinja2 模板中导入 URL
类:
{{ url_for('decline_event_invite').include_query_params(event_invite=invite.id, sender=invite.sender) }}