我正在使用基于类的视图(FormView),我希望在提交表单后保留搜索关键字(POST请求)。我在form_valid
方法中尝试了这个:
def form_valid(self, form):
self.initial['search'] = form.data['search']
...
但这将为所有用户显示。这是许多网络搜索表单(更不用说Google搜索)的常见解决方案,所以我想知道如何在Django中完成这项工作。
更新:2016年6月19日星期一13:18:42 UTC
根据以下一些答案,我将不得不重新提出我的问题。
我有一个带有几个输入字段的简单表单,在提交表单后,它将查询其他网站以根据搜索字词获取结果。我想将一些结果存储到数据库中,主要是为了生成统计数据,重新显示包含所选字段的表单并显示结果。
目前,数据驻留在一个类对象上,并且它从POST传递给GET。出于明显的安全原因,这不是一个好的解决方案:
class SearchView(FormView):
...
data = dict()
def form_valid(self, form):
....
self.data['results'] = results
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
context['data'] = self.data.pop('results', None)
return context
问题:
在同一页面上显示表单(包含所选字段)和结果的最佳方式是什么,最好不要在会话中将其存储在POST和GET之间的数据库中。
我已经考虑过的要点:
不要重定向用户(立即使用当前上下文呈现模板,而我们仍然有响应对象) - 我不喜欢页面刷新将重新提交的事实形式。
将响应保存到像Redis这样的键值存储中,并将用户重定向到结果/ {result_id}之类的地方,我们可以从数据库中检索响应,用数据预先填充表单并显示结果 - 这听起来很合理但我必须添加另一个组件才能将结果从POST传递给GET。
对这种形式使用GET - 我的理解是我们应该使用POST进行数据修改
答案 0 :(得分:4)
Google和其他类似搜索使用GET
参数传递查询字符串
<强>〔实施例强>:
test
https://www.google.ru/?q=test
所以基本上你需要使用相同的方法并将搜索字符串作为GET
param。
这是一般性的想法
class SearchView(View):
success_url = reverse('result-view')
def get_success_url(self):
success_url = super().get_success_url()
return '{0}?search={1}'.format(success_url, self.form.cleaned_data['search'])
...
class ResultView(View):
def get(self, request, *args, **kwargs):
search_string = request.GET.get('search', '')
答案 1 :(得分:2)
您没有明确说明您希望保留关键字的时长。
如果仅仅是响应,只要您正确呈现表单,关键字仍然会存在:
>>> from django import forms
>>> class MyForm(forms.Form):
... search = forms.CharField()
...
>>> f = MyForm(data={'search': 'KEYWORD'})
>>> print(f['search'])
<input id="id_search" name="search" type="text" value="KEYWORD" />
如果您希望将关键字保留在请求中但仅针对该用户,请使用sessions framework:
def form_valid(self, form):
self.request.session['search'] = form.data['search']
...
def get_form(self, form_class):
form = super(self, YourView).get_form(form_class)
form.initial['search'] = self.request.session.get('search', '')
return form
答案 2 :(得分:2)
<强> views.py 强>
d
<强> HTML 强>
class SearchView(FormView):
template_name = 'apps/frontend/search_view.j2'
def get_form_class(self):
class _Form(forms.Form):
search = forms.CharField(label='search')
return _Form
def form_valid(self, form):
return self.render_to_response(self.get_context_data(form=form))
答案 3 :(得分:2)
从您的更新:我认为这是您正在寻找的过程:
当表单有效时,您基本上需要阻止重定向:
class SearchPageView(FormView):
def form_valid(self, form):
# do your things (3) here
context = self.get_context_data(form=form)
context['results'] = ['lorem', 'ipsum']
return self.render_to_response(context)
答案 4 :(得分:2)
这是我认为满足您所有要求的实施方案。特别是,我们可以通过form_valid()
返回super(SearchView, self).get(self.request)
来重新提示用户的输入。这样,Django服务器就像从用户的角度处理正常的POST操作一样。
<强> views.py 强>
class SearchView(FormView):
template_name = 'yourapp/search.html'
form_class = SearchForm
results = '' # for {{ view.results }}
def form_valid(self, form):
self.results = form.get_results()
return super(SearchView, self).get(self.request)
<强> forms.py 强>
class SearchForm(forms.Form):
input = forms.CharField()
def get_results(self):
input_data = self.cleaned_data['input']
results = "results for %s" % input_data # <-- modify this process as you need
# ... (your operations for input_data and results here)
return results
<强> yourapp / search.html 强>
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Search" />
</form>
<p>{{ view.results }}</p>
答案 5 :(得分:2)
对这种形式使用GET - 我的理解是我们应该这样做 使用POST进行数据修改
仅使用GET填充form.initial
值,您仍然可以将表单作为POST提交。
# for python3
# from urllib.parse import urlencode
from urllib import urlencode
class SearchView(FormView):
def get_initial(self):
return {'search': self.request.GET.get('search')}
def form_valid(self, form):
search = self.request.POST.get('search')
url = self.get_success_url() + '?' + urlencode({'search': search})
return HttpResponseRedirect(url)
答案 6 :(得分:1)
我仍然对你想要做的事情有点不确定(通常通过GET进行搜索,然后Django表现出所需的行为)。但我认为你应该可以通过覆盖get_initial():
并从self.request.POST
中提取值来实现这一目标。
如果你想要做的就是将提交的值保留在下一个值的初始化中,这是最好的方法。
即。在Python 3的View类中有类似的东西(你的超级调用需要在Python 2中有所不同):
def get_initial(self):
initial = super().get_initial()
initial['search'] = self.request.POST.get('search', '')
return initial