From e429c5186ceed81c4627165518e0c70c58e69595 Mon Sep 17 00:00:00 2001
From: Chris Cogdon <chris.cogdon@dtexsystems.com>
Date: Wed, 30 Dec 2015 13:22:58 -0800
Subject: [PATCH] Fixed #26018 -- Prevented unecessary get_form() call in
 FormMixin.get_context_data().

Changed "dict.setdefault" to "if x in dict" pattern so that get_form() would not
be called unnecessarily, specifically in the case where FormMixin.form_invalid()
calls get_context_data() with the current form.
---
 django/views/generic/edit.py     | 3 ++-
 docs/releases/1.9.1.txt          | 2 +-
 tests/generic_views/test_edit.py | 2 ++
 tests/generic_views/views.py     | 5 +++++
 4 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/django/views/generic/edit.py b/django/views/generic/edit.py
index 644110f9ea..33e3a1b80c 100644
--- a/django/views/generic/edit.py
+++ b/django/views/generic/edit.py
@@ -89,7 +89,8 @@ class FormMixin(ContextMixin):
         """
         Insert the form into the context dict.
         """
-        kwargs.setdefault('form', self.get_form())
+        if 'form' not in kwargs:
+            kwargs['form'] = self.get_form()
         return super(FormMixin, self).get_context_data(**kwargs)
 
 
diff --git a/docs/releases/1.9.1.txt b/docs/releases/1.9.1.txt
index 143db5e596..9af92e30ef 100644
--- a/docs/releases/1.9.1.txt
+++ b/docs/releases/1.9.1.txt
@@ -13,7 +13,7 @@ Bugfixes
   (:ticket:`25840`).
 
 * Fixed a regression in ``FormMixin`` causing forms to be validated twice
-  (:ticket:`25548`).
+  (:ticket:`25548`, :ticket:`26018`).
 
 * Fixed a system check crash with nested ``ArrayField``\s (:ticket:`25867`).
 
diff --git a/tests/generic_views/test_edit.py b/tests/generic_views/test_edit.py
index 5b4bec96af..ba855f3cd1 100644
--- a/tests/generic_views/test_edit.py
+++ b/tests/generic_views/test_edit.py
@@ -232,6 +232,7 @@ class UpdateViewTests(TestCase):
         self.assertEqual(res.context['object'], Author.objects.get(pk=a.pk))
         self.assertEqual(res.context['author'], Author.objects.get(pk=a.pk))
         self.assertTemplateUsed(res, 'generic_views/author_form.html')
+        self.assertEqual(res.context['view'].get_form_called_count, 1)
 
         # Modification with both POST and PUT (browser compatible)
         res = self.client.post('/edit/author/%d/update/' % a.pk,
@@ -251,6 +252,7 @@ class UpdateViewTests(TestCase):
         self.assertTemplateUsed(res, 'generic_views/author_form.html')
         self.assertEqual(len(res.context['form'].errors), 1)
         self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>'])
+        self.assertEqual(res.context['view'].get_form_called_count, 1)
 
     def test_update_with_object_url(self):
         a = Artist.objects.create(name='Rene Magritte')
diff --git a/tests/generic_views/views.py b/tests/generic_views/views.py
index 01f044156d..11e1ec3b4d 100644
--- a/tests/generic_views/views.py
+++ b/tests/generic_views/views.py
@@ -147,10 +147,15 @@ class NaiveAuthorUpdate(generic.UpdateView):
 
 
 class AuthorUpdate(generic.UpdateView):
+    get_form_called_count = 0  # Used to ensure get_form() is called once.
     model = Author
     success_url = '/list/authors/'
     fields = '__all__'
 
+    def get_form(self, *args, **kwargs):
+        self.get_form_called_count += 1
+        return super(AuthorUpdate, self).get_form(*args, **kwargs)
+
 
 class OneAuthorUpdate(generic.UpdateView):
     success_url = '/list/authors/'