Django在POST请求后设置表单字段

时间:2017-06-13 21:43:14

标签: django

我正在使用基于类的视图(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之间的数据库中。

我已经考虑过的要点:

  1. 不要重定向用户(立即使用当前上下文呈现模板,而我们仍然有响应对象) - 我不喜欢页面刷新将重新提交的事实形式。

  2. 将响应保存到像Redis这样的键值存储中,并将用户重定向到结果/ {result_id}之类的地方,我们可以从数据库中检索响应,用数据预先填充表单并显示结果 - 这听起来很合理但我必须添加另一个组件才能将结果从POST传递给GET。

  3. 对这种形式使用GET - 我的理解是我们应该使用POST进行数据修改

7 个答案:

答案 0 :(得分:4)

Google和其他类似搜索使用GET参数传递查询字符串

<强>〔实施例

  1. Google test
  2. 结果网址为https://www.google.ru/?q=test
  3. 所以基本上你需要使用相同的方法并将搜索字符串作为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)

从您的更新:我认为这是您正在寻找的过程:

  1. 用户使用空搜索字词填写表单
  2. 用户使用搜索字词
  3. 发布表单
  4. 您在此POST请求中查询其他网站,并使用术语
  5. 再次显示您的表单
  6. 向用户显示预填表格和结果(无重定向或您将失去上下文)
  7. 当表单有效时,您基本上需要阻止重定向:

    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
相关问题