Flask:如何在基础 jinja2 模板中放置表单?

2 投票
1 回答
6855 浏览
提问于 2025-04-18 09:42

我刚开始学习Flask,正在写一个简单的Flask应用程序,里面有搜索功能。就像谷歌搜索一样,我希望在搜索结果页面保留搜索输入框,同时显示搜索结果。所以,我把搜索表单放在了基础模板中,并从这个基础模板派生出一个搜索结果模板,以便同时显示搜索表单和搜索结果。

为此,我做了以下几步:

首先,我创建了一个基础模板(base.html),里面包含页面的基本信息和表单(这个表单在结果页面也应该存在)。

<html>
  <head>
    {% if title %}
    <title>{{title}}</title>
    {% else %}
    <title>Search</title>
    {% endif %}
  </head>
  <body>
    <h1>Search </h1>
<form action="/series_search" method="post" name="search">
    {{form.hidden_tag()}}
    <p>
        Please enter query: <br>
        {{form.search(size=10)}}
    </p>
    <p><input type="submit" value="Search"></p>
</form>
<br>
{% block content %}{% endblock %}

  </body>
</html>

然后,派生的模板(derived.html)包含以下代码,它继承了基础模板(也就是包含搜索表单的模板):

{% extends "base.html" %}

{% block content %}
<h1>Search Result</h1>
    {% if result %}
    <p> Title: {{result.title}}</p>
    {% else %}
    <p> search not found!!</p>
    {% endif %}
{% endblock %}

接着,在视图中,我写了以下代码:

@app.route('/search', methods = ['POST', 'GET'])
def search():
    form = SearchForm()
    if form.validate_on_submit():
        print "form validated"
        query = form.search.data
        result = Lib.get_result(query)
        return render_template('derived.html', result = result)
    return render_template('search.html',
    title = 'Search',
    form = form)

如果我输入查询内容并提交搜索表单,就会出现以下错误:

....
....
File "/Users/webapp/app/templates/derived.html", line 1, in top-level template code
    {% extends "search.html" %}
  File "/Users/webapp/app/templates/search.html", line 12, in top-level template code
    {{form.hidden_tag()}}
  File "/Users/webapp/flask/lib/python2.7/site-packages/jinja2/environment.py", line 397, in getattr
    return getattr(obj, attribute)

简单来说,当我按下提交按钮后,视图会渲染派生的derived.html,这个模板是从base.html派生而来的。base.html里有一个表单,应该被设置好。

  1. 我该如何在调用派生模板时传递基础模板的表单对象?
  2. 我的方法是否正确?如果有其他更好的方法,请告诉我。

提前感谢你的帮助!

1 个回答

6

你只需要在另一个 render_template 调用中传递表单的关键字参数。

return render_template('derived.html', result=result)

应该改成:

return render_template('derived.html', result=result, form=form)

这样做的原因是因为网络是无状态的——Flask 不会保存渲染后的模板。HTML 会发送给客户端,然后就结束了,Flask 认为一切都完成了。POST 请求在服务器的角度来看是一个独立的请求,唯一被调用的就是 render_template('derived') 这个调用。Flask 并没有“记住”之前创建过一个表单并把它发送到 search.html

撰写回答