python - 如何重定向到 FastAPI 端点内的动态 URL?

标签 python redirect jinja2 fastapi

我正在做一项功能,用户可以在其个人资料页面上进行更改(与用户模型无关)。一切都是通过静态 HTML 模板实现的。我需要用户在处理请求后单击按钮并返回到同一页面(即他们的个人资料页面)。

HTML 模板

<td><a href="{{ url_for('decline_event_invite', pk=invite.id) }}" class="btn blue lighten-2">Accept</a></td>

endpoints.py

@router.get('/invite/{pk}/decline')
async def decline_event_invite(
        request: Request,
        pk: int,
        user_id: str = Depends(get_current_user),
        service: InviteService = Depends(),
):
    await service.invite_decline(pk)
    ...
    --> here I want redirect to user profile page 
    return RedirectResponse('DYNAMIC URL WITH ARGS')

profile.py

@router.get('/{pk}')
async def user_profile(
        request: Request,
        pk: int,
        service: UserService = Depends()
):
    user = await service.get_user_info(pk)
    events_invites = await service.get_user_events_invite_list(pk)
    return templates.TemplateResponse(
        'profile.html',
        context=
        {
            'request': request,
            'user': user,
            'events_invites': events_invites,
        }
    )

但我无法在任何地方找到如何执行类似于适用于模板的逻辑的重定向。例如:

<a href="{{ url_for('user_profile', pk=pk) }}">Sender</a>

最佳答案

您可以使用url_for()函数并传递(**kwargs)路径参数。

import uvicorn
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import RedirectResponse
import urllib
from fastapi import APIRouter

app = FastAPI()

templates = Jinja2Templates(directory="templates")

@app.get('/invite/{pk}/decline')
def decline_event_invite(request: Request, pk: int):
    redirect_url = request.url_for('user_profile', **{ 'pk' : pk})
    return RedirectResponse(redirect_url)    

@app.get('/{pk}')
def user_profile(request: Request, pk: int):
    return templates.TemplateResponse("profile.html", {"request": request, "pk": pk})
    

添加查询参数

如果您还必须传递查询参数,您可以使用以下代码(确保导入 urllib)。或者,您可以使用 CustomURLProcessor,如 this 中所述。和 this答案(几乎遵循相同的方法)。

如果端点需要查询参数,例如:

@router.get('/{pk}')
def user_profile(request: Request, pk: int, message: str):
    pass

你可以使用:

redirect_url = request.url_for('user_profile', pk=pk)
parsed = list(urllib.parse.urlparse(redirect_url))
parsed[4] = urllib.parse.urlencode({**{ 'message' : "Success!"}})
redirect_url = urllib.parse.urlunparse(parsed)

甚至使用:

message = 'Success!'
redirect_url = request.url_for('user_profile', pk=pk) + f'?message={message}'

更新 1 - 关于包含查询参数

另一个解决方案是使用 Starlette 的 starlette.datastructures.URL ,现在提供了一个方法 include_query_params 。示例:

from starlette.datastructures import URL

redirect_url = URL(request.url_for('user_profile', pk=pk)).include_query_params(message="Success!")

更新 2 - 关于包含查询参数

request.url_for()函数现在返回 starlette.datastructures.URL目的。因此,您可以简单地使用包含查询参数,如下所示:

redirect_url = request.url_for('user_profile', pk=pk).include_query_params(message="Success!")

关于python - 如何重定向到 FastAPI 端点内的动态 URL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70656412/

相关文章:

scripting - 在ansible中展平和过滤复杂的结构 - 字典列表的字典

python - 如何在 python 中打印括号

Python正则表达式与unicode字符错误?

python - 如何导入具有复杂字段的csv

python - 将 dict 转换为 defaultdict

ajax - 在 AJAX 中处理来自跨源帖子的重定向

jsf - 如何在 JSF 中将对象从一个页面传递到另一个页面而不编写转换器

.htaccess - 将所有域的所有站点重定向到新域而无需尾随查询字符串

jinja2 - 在 Apache Airflow 的 S3KeySensor 中模板化 `bucket_key`

python - 如何对 jinja2 进行单元测试?