Flask:如何在基础 jinja2 模板中放置表单?
我刚开始学习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 个回答
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
。