处理表单提交分页的正确方法?

Correct way to handle pagination with form submission?

我有一个用于在搜索页面上进行搜索的表单:

<form action="{{ url_for('searchresults') }}" method="get" name="noname" id="theform">
    {{ form2.page(id="hiddenpage") }}
    ... some form inputs
    <button id = "mybutton" type = "submit" >Apply</button>
</form>

表格是SearchForm,其中

class SearchForm(Form):
    page = HiddenField()
    categories = SelectMultipleField(u'Text', validators=[Optional()])
    # some other stuff...

searchresults 的视图处理表单:

@app.route('/searchresults', methods=['GET'])
def searchresults():
    form = SearchForm()
    # handle the form and get the search results using pagination
    page = int(request.args.getlist('page')[0])
    results = models.Product.query....paginate(page, 10, False)
    return render_template('searchresults.html', form=form, results=results, curpage=page)

render_template中的results将是我查询的前10个结果。在 searchresults.html 中,我显示结果,以及 nextprevious link 其他结果。此页面还包含我根据初始提交重新设置的相同搜索表单。目前我正在使用

处理 nextprevious link
<a href="#" onclick="$('#hiddenpage').val( {{ curpage+1 }} ); $('#theform').submit();"> Next </a>

因此 next link 重新提交相同的初始表单,但 page 值增加。我对这种方法不是很满意,因为当我将鼠标悬停在 next link 上时,我看不到我将被定向到的实际页面。它也开始感觉有点像黑客。有没有更自然的方法来做到这一点?最初提交表单时,我可以用它来创建一长串所需参数,并在呈现的页面中将该字符串用作 href=" {{ url_for('searchresults') }}?mystring",但这似乎也不自然。我该如何处理?

您已将表单配置为作为 GET 请求提交,因此您实际上不需要通过 Javascript 强制重新提交,您可以通过设置nextprev 指向包含表单中所有参数的 URL 的链接,页面已修改为正确的下一页和上一页页码。

url_for() 这真的很容易做到。您添加的任何与路由组件不匹配的参数都将添加到查询字符串中,因此您可以这样做:

<a href="{{ url_for('searchresults', categories=form.categories.data, page=form.page.data+1) }}"> Next </a>

要记住的一件事是 CSRF。如果您在表单中启用了它,那么您的 next/prev 网址也需要有一个有效的令牌。或者您可以禁用 CSRF,这对于搜索表单可能没问题。

利用您的表单参数已经存在于 URL 中这一事实,并使用 request.args 将 URL 参数传递到您的表单中:

form = SearchForm(request.args)

然后,如果您将 page 字段设为 IntegerField with a HiddenInput 小部件而不是字符串字段:

from wtforms.widgets import HiddenInput

class SearchForm(Form):
    page = HiddenField(widget=HiddenInput, default=1)

您可以在将表单传递到搜索结果页面之前递增 page

form.page.data += 1

然后,在您的页面中,您只需创建 link 到下一页:

<a href="{{ url_for('searchresults', **form.data) }}">Next</a>