15

Currently, I have a form that looks like this:

class SelectBoard(generic.FormView):
    form_class = forms.SelectBoard

    def form_valid(self, form):
        board_name = form.cleaned_data['name']
        return redirect('leaderboard', board_name=board_name)

However, it would be my preference to do the more idiomatic thing, and use get_success_url. Something like this:

class SelectBoard(generic.FormView):
    form_class = forms.SelectBoard

    def get_success_url(self):
        form = ???
        board_name = form.cleaned_data['name']
        return reverse('leaderboard', board_name=board_name)

However, the form is not passed to get_success_url, and unlike many other pieces of request context (like self.request, self.kwargs, or self.object (in DetailView)), the form is not attached as an attribute at any point in the standard FormView dispatch sequence. Is there any good way to access cleaned & validated form data in get_success_url (that is, without having to access self.request.POST or reconstruct the form from scratch)?

Lucretiel
  • 3,145
  • 1
  • 24
  • 52

2 Answers2

11

You can override form_valid method to write form as instance attribute and use self.form inside get_success_url:

class SelectBoard(generic.FormView):
    form_class = forms.SelectBoard

    def form_valid(self, form):
        """If the form is valid, redirect to the supplied URL."""
        self.form = form    
        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        board_name = self.form.cleaned_data['name']
        return reverse('leaderboard', board_name=board_name)
neverwalkaloner
  • 46,181
  • 7
  • 92
  • 100
  • 3
    This was one of my thoughts– overriding `get_form` to do the same thing was another one– but it seemed like a shame, since the whole point is to not have to add any extra code to `form_valid`, since the default behavior works great *except* that there's no way to access the form from `get_success_url` – Lucretiel Feb 03 '18 at 19:52
0

You might set the success_url attribute in form_valid method getting the form field value if it is needed

class SelectBoard(generic.FormView):
    form_class = forms.SelectBoard

    def form_valid(self, form):
        board_name = form.cleaned_data['name']
        self.success_url = reverse('leaderboard', board_name=board_name)

        return super().form_valid(form)
Rafael Maciel
  • 135
  • 1
  • 3
  • 1
    Sure, but if I'm writing a `form_valid` method I can just do when I do in my question. I'm trying to avoid that. – Lucretiel Jul 19 '19 at 03:45