From 636c45fc58bcc19d7669a739ccd05ff475381f48 Mon Sep 17 00:00:00 2001
From: Christopher Medrela <chris.medrela@gmail.com>
Date: Sun, 24 Feb 2013 16:49:28 +0100
Subject: [PATCH] Fixed #19890 -- ifchanged templatetag rendered its content
 twice

The content of ifchanged template tag was rendered twice: first time, to
compare it with the previous value and the second time, to return the
rendered output.
---
 django/template/defaulttags.py           |  5 +++--
 tests/regressiontests/templates/tests.py | 12 ++++++++++++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py
index 7c0772cda8..dbb5b5a0cb 100644
--- a/django/template/defaulttags.py
+++ b/django/template/defaulttags.py
@@ -223,6 +223,7 @@ class IfChangedNode(Node):
         if self not in state_frame:
             state_frame[self] = None
 
+        nodelist_true_output = None
         try:
             if self._varlist:
                 # Consider multiple parameters.  This automatically behaves
@@ -230,13 +231,13 @@ class IfChangedNode(Node):
                 compare_to = [var.resolve(context, True) for var in self._varlist]
             else:
                 # The "{% ifchanged %}" syntax (without any variables) compares the rendered output.
-                compare_to = self.nodelist_true.render(context)
+                compare_to = nodelist_true_output = self.nodelist_true.render(context)
         except VariableDoesNotExist:
             compare_to = None
 
         if compare_to != state_frame[self]:
             state_frame[self] = compare_to
-            return self.nodelist_true.render(context)
+            return nodelist_true_output or self.nodelist_true.render(context)  # render true block if not already rendered
         elif self.nodelist_false:
             return self.nodelist_false.render(context)
         return ''
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index 28d85cae9d..e1e448acba 100644
--- a/tests/regressiontests/templates/tests.py
+++ b/tests/regressiontests/templates/tests.py
@@ -441,6 +441,18 @@ class Templates(TestCase):
         output1 = template.render(Context({'foo': range(3), 'get_value': lambda: next(gen1)}))
         self.assertEqual(output1, '[0,1,2,3]', 'Expected [0,1,2,3] in first template, got {0}'.format(output1))
 
+    def test_ifchanged_render_once(self):
+        """ Test for ticket #19890. The content of ifchanged template tag was
+        rendered twice."""
+
+        template = Template('{% ifchanged %}{{ gen.next }}{% endifchanged %}')
+        def gen():
+            for i in xrange(1,10):
+                yield 'iteration no %d' % i
+
+        output = template.render(Context({'gen': gen()}))
+        self.assertEqual(output, 'iteration no 1')
+
     def test_templates(self):
         template_tests = self.get_template_tests()
         filter_tests = filters.get_filter_tests()