Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django set form field after POST request

Tags:

django

I'm using class-based views (FormView) and I would like to keep a search keyword after form is submitted (POST request). I tried this in form_valid method:

def form_valid(self, form):
        self.initial['search'] = form.data['search']
        ...

but this will show it for all users. This is quite common solution on many web search forms (not to mention Google search) so I wonder how this can be done in Django.

Update: Mon 19 Jun 13:18:42 UTC 2017

Based on some answers below I'll have to rephrase my question.

I have a simple form with a few input fields, after a form is submitted it will query other sites to get the results based on a search term. I would like to store some results into database, mainly to produce stats, re-display the form with selected fields and show results.

Currently data resides on a class object and it's passed from POST to GET. This is not a good solution for obvious security reasons:

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

Question:

What would be the best way to display form (with selected fields) and results on the same page, preferably without sessions or storing them in database between POST and GET.

Points that I already considered:

  1. Don't redirect the user (render the template with the current context right away, while we still have the response object) - I don't like the fact that page refresh will re-submit the form.

  2. Save the response into some key-value store like Redis and redirect the user to something like results/{result_id}, where we can retrieve the response from database to pre-fill the form with data and show the results - this sounds reasonable but I'll have to add another component just to pass the results from POST to GET.

  3. Use GET for this type of form - my understanding was that we should use POST for data modification

like image 787
HTF Avatar asked Jun 13 '17 21:06

HTF


2 Answers

Google and other similar searches use GET params to pass query string

Exmaple:

  1. Google test
  2. Result url will be https://www.google.ru/?q=test

So basically you need to use same approach and pass you search string as GET param.

Here is general Idea

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', '')
like image 113
Sardorbek Imomaliev Avatar answered Sep 30 '22 14:09

Sardorbek Imomaliev


From your update: I think this is the process you are looking for:

  1. user fills the form with empty search term
  2. user POST the form with search term
  3. you query other sites in this POST request, and display your form again with term
  4. user is presented with the pre-filled form and results (no redirection or you would lose context)

You basically need to prevent the redirection when form is valid:

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)
like image 23
SebCorbin Avatar answered Sep 30 '22 15:09

SebCorbin