【问题标题】:how to use url_for() to pass data to another route? fastapi & jinja2如何使用 url_for() 将数据传递到另一个路由? fastapi & jinja2
【发布时间】:2021-03-05 16:15:23
【问题描述】:

我想从 jinja2 模板调用 fastapi 路由并将数据传递给被调用的路由。我所有的尝试都失败了。 我在 jinja2 模板中尝试了一些东西,例如 {{ url_for('function1', uustr=data.uustr, interval=1) }}

这是我要调用的 fastapi 路由(为演示目的简化了语法):

@app.get("/updates/data/{uustr}",response_class=HTMLResponse)
async def function1(request: Request, uustr:str, interval:int):

  return"""
<html>
    <head>
        <title>{{ uustr }}</title>
    </head>
    <body>
        <h1>{{ interval }}</h1>
    </body>
</html>
"""

我收到此错误:

    raise ValueError('context must include a "request" key') 
ValueError: context must include a "request" key

有人有想法吗?

【问题讨论】:

  • 你看过 jinja 模板的 FastAPI 文档吗?看起来他们的做法与你的完全不同:fastapi.tiangolo.com/advanced/templates/#using-jinja2templates
  • 是的,我看到了,你是对的。那里的用法不同。在文档中,他们使用url_for() 来定位文件夹。我想用它来调用路由。至少在烧瓶中这样的事情是可能的。我也希望在 fastapi 中

标签: python jinja2 fastapi


【解决方案1】:

我找到了一个非常简单的解决方案,无需使用url_for()

如果来自烧瓶世界的人在这里遇到类似的问题,我的解决方案: 我在我的 jinja2 模板中创建了一个简单的 HTML 按钮:

<button onclick="myFunction()">pass data to route</button>

我创建了一个非常简单的 javascript 函数来将数据传递给路由:

<script>
function myFunction() {
  window.location.href = "/updates/data/{{data.uustr}}?interval=2";
}
</script>

就是这样。

【讨论】:

    【解决方案2】:

    这不是 FastAPI 的问题,而是 Starlette's 的问题(即 request.url_for() 接收路径参数,不是查询参数)。因此,受#560#1385 的启发,我创建了以下工作示例,用于从 jinja2 模板中调用 FastAPI 路由,并传递 query 参数(单独或与 path em> 参数,以及)。

    请注意,此功能可能即将引入下一版 Starlette #1385。因此,最好在它用完时使用它。

    app.py

    import uvicorn
    from fastapi import FastAPI, Response
    from fastapi.templating import Jinja2Templates
    from fastapi import Request
    from fastapi.responses import StreamingResponse, 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}')
    async 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')
    async def updates_query_only(request: Request, user: str, msg: str):
        return templates.TemplateResponse("item.html", {"request": request, "user": user, "msg": msg})
    
    
    @app.get('/')
    async 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)
    

    模板/index.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>
    

    模板/item.html

    <!DOCTYPE html>
    <html>
        <body>
            <h1>Page No {{ page_no }}</h1>
            <h2>Item {{ item_id }}</h2>
            <h3>{{ user }}</h3>
            <h4>{{ msg }}</h4>
        </body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 2019-09-22
      • 2022-08-09
      • 1970-01-01
      • 2017-08-16
      • 1970-01-01
      • 2020-11-26
      • 2017-03-12
      • 2020-12-19
      • 1970-01-01
      相关资源
      最近更新 更多