从 Jinja 模板发送查询参数
Send query params from Jinja template
我不知道是否可以将查询参数从静态 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
events.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's issue(即url_for()
接收path
参数,不是query
参数)。您可以做的是创建一个自定义 URL 处理器(如下所示)并使用它来传递 path
and/or query
参数。
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
class 添加到模板的全局环境中:
templates.env.globals['CustomURLProcessor'] = CustomURLProcessor
然后,在Jinja模板中使用,如下:
{{ CustomURLProcessor().url_for(request, 'decline_event_invite').include_query_params(event_invite=invite.id, sender=invite.sender) }}
请看this answer for a complete working example. Also, this feature might be introduced into the next version of Starlette #1385。因此,您可能需要关注它。
更新
使 CustomURLProcessor
class 可从 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})
如果上述 none 有效,则描述的其他选项 here 可能会有所帮助,或者问题可能出在其他地方。
我不知道是否可以将查询参数从静态 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
events.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's issue(即url_for()
接收path
参数,不是query
参数)。您可以做的是创建一个自定义 URL 处理器(如下所示)并使用它来传递 path
and/or query
参数。
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
class 添加到模板的全局环境中:
templates.env.globals['CustomURLProcessor'] = CustomURLProcessor
然后,在Jinja模板中使用,如下:
{{ CustomURLProcessor().url_for(request, 'decline_event_invite').include_query_params(event_invite=invite.id, sender=invite.sender) }}
请看this answer for a complete working example. Also, this feature might be introduced into the next version of Starlette #1385。因此,您可能需要关注它。
更新
使 CustomURLProcessor
class 可从 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})
如果上述 none 有效,则描述的其他选项 here 可能会有所帮助,或者问题可能出在其他地方。