From 0154702a987bd06d20e53fe23284b2c4a93b9063 Mon Sep 17 00:00:00 2001 From: Alex Morozov Date: Tue, 10 Nov 2015 16:06:59 +0300 Subject: [PATCH] [1.9.x] Fixed #25548 -- Prevented FormView.form_invalid() from discarding its form argument. Backport of e171a83b1516a3a2a393a5300527af1aab21c213 from master --- django/views/generic/edit.py | 2 +- docs/releases/1.9.1.txt | 3 +++ tests/generic_views/test_edit.py | 7 +++++++ tests/generic_views/urls.py | 2 ++ tests/generic_views/views.py | 10 ++++++++++ 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/django/views/generic/edit.py b/django/views/generic/edit.py index 9120e1dd76..4ebf06a497 100644 --- a/django/views/generic/edit.py +++ b/django/views/generic/edit.py @@ -112,7 +112,7 @@ class FormMixin(six.with_metaclass(FormMixinBase, ContextMixin)): If the form is invalid, re-render the context data with the data-filled form and errors. """ - return self.render_to_response(self.get_context_data()) + return self.render_to_response(self.get_context_data(form=form)) def get_context_data(self, **kwargs): """ diff --git a/docs/releases/1.9.1.txt b/docs/releases/1.9.1.txt index 91a0f33a2a..e7c0bfeceb 100644 --- a/docs/releases/1.9.1.txt +++ b/docs/releases/1.9.1.txt @@ -11,3 +11,6 @@ Bugfixes * Fixed ``BaseCache.get_or_set()`` with the ``DummyCache`` backend (:ticket:`25840`). + +* Fixed a regression in ``FormMixin`` causing forms to be validated twice + (:ticket:`25548`). diff --git a/tests/generic_views/test_edit.py b/tests/generic_views/test_edit.py index e93965a670..e0730b1118 100644 --- a/tests/generic_views/test_edit.py +++ b/tests/generic_views/test_edit.py @@ -98,6 +98,13 @@ class BasicFormTests(TestCase): res = self.client.post('/contact/', {'name': "Me", 'message': "Hello"}) self.assertRedirects(res, '/list/authors/') + def test_late_form_validation(self): + """ + A form can be marked invalid in the form_valid() method (#25548). + """ + res = self.client.post('/late-validation/', {'name': "Me", 'message': "Hello"}) + self.assertFalse(res.context['form'].is_valid()) + class ModelFormMixinTests(SimpleTestCase): def test_get_form(self): diff --git a/tests/generic_views/urls.py b/tests/generic_views/urls.py index d455924a9e..85a6243b7f 100644 --- a/tests/generic_views/urls.py +++ b/tests/generic_views/urls.py @@ -65,6 +65,8 @@ urlpatterns = [ # FormView url(r'^contact/$', views.ContactView.as_view()), + url(r'^late-validation/$', + views.LateValidationView.as_view()), # Create/UpdateView url(r'^edit/artists/create/$', diff --git a/tests/generic_views/views.py b/tests/generic_views/views.py index b40bbe92f0..b66418eb7b 100644 --- a/tests/generic_views/views.py +++ b/tests/generic_views/views.py @@ -307,3 +307,13 @@ class NonModelDetail(generic.DetailView): class ObjectDoesNotExistDetail(generic.DetailView): def get_queryset(self): return Book.does_not_exist.all() + + +class LateValidationView(generic.FormView): + form_class = ContactForm + success_url = reverse_lazy('authors_list') + template_name = 'generic_views/form.html' + + def form_valid(self, form): + form.add_error(None, 'There is an error') + return self.form_invalid(form)