Index: tests/regressiontests/templates/tests.py
===================================================================
--- tests/regressiontests/templates/tests.py	(revision 16253)
+++ tests/regressiontests/templates/tests.py	(working copy)
@@ -963,6 +963,21 @@
 
             'ifchanged-else04': ('{% for id in ids %}{% ifchanged %}***{{ id }}*{% else %}...{% endifchanged %}{{ forloop.counter }}{% endfor %}', {'ids': [1,1,2,2,2,3,4]}, '***1*1...2***2*3...4...5***3*6***4*7'),
 
+            ### IFNOTEMPTY TAG #########################################################
+            'ifnotempty01': ('{% ifnotempty %}hello{% endifnotempty %}', {}, ''),
+            'ifnotempty02': ('{% ifnotempty %}pre {{ var }} post{% endifnotempty %}', {'var': ''}, ''),
+            'ifnotempty03': ('{% ifnotempty %}pre {{ var }} post{% endifnotempty %}', {'var': 'abc'}, 'pre abc post'),
+            'ifnotempty04': ('{% ifnotempty %}pre {% for n in nums %}{{ n }},{% endfor %} post{% endifnotempty %}', {'nums': ()}, ''),
+            'ifnotempty05': ('{% ifnotempty %}pre {% for n in nums %}{{ n }},{% endfor %} post{% endifnotempty %}', {'nums': (1,2,3)}, 'pre 1,2,3, post'),
+
+            # Test the behaviour when enclosing a block
+            'ifnotempty-inheritance01': ("{% ifnotempty %}pre {% block replaceme %}{% endblock %} post{% endifnotempty %}", {}, ''),
+            'ifnotempty-inheritance02': ("{% extends 'ifnotempty-inheritance01' %}{% block replaceme %}mid{% endblock %}", {}, 'pre mid post'),
+            
+            # # Test the else clause of ifnotempty.
+            'ifnotempty-else01': ('{% ifnotempty %}pre {{ var }} post{% else %}other{% endifnotempty %}', {'var': ''}, 'other'),
+            'ifnotempty-else02': ('{% ifnotempty %}pre {{ var }} post{% else %}other{% endifnotempty %}', {'var': 'abc'}, 'pre abc post'),
+
             ### IFEQUAL TAG ###########################################################
             'ifequal01': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 2}, ""),
             'ifequal02': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 1}, "yes"),
Index: django/template/defaulttags.py
===================================================================
--- django/template/defaulttags.py	(revision 16253)
+++ django/template/defaulttags.py	(working copy)
@@ -5,13 +5,13 @@
 from datetime import datetime
 from itertools import groupby, cycle as itertools_cycle
 
-from django.template.base import Node, NodeList, Template, Context, Variable
+from django.template.base import Node, NodeList, Template, TextNode, Context, Variable
 from django.template.base import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END
 from django.template.base import get_library, Library, InvalidTemplateLibrary
 from django.template.smartif import IfParser, Literal
 from django.template.defaultfilters import date
 from django.conf import settings
-from django.utils.encoding import smart_str, smart_unicode
+from django.utils.encoding import force_unicode, smart_str, smart_unicode
 from django.utils.safestring import mark_safe
 
 register = Library()
@@ -269,6 +269,37 @@
             return self.nodelist_false.render(context)
         return ''
 
+class IfNotEmptyNodeList(NodeList):
+    def render_conditionally(self, context):
+        any_node_rendered = False
+        bits = []
+        for node in self:
+            if isinstance(node, TextNode):
+                bits.append(self.render_node(node, context))
+            elif isinstance(node, Node):
+                bit = self.render_node(node, context)
+                if bit:
+                    any_node_rendered = True
+                bits.append(bit)
+            else:
+                bits.append(node)
+        return mark_safe(''.join([force_unicode(b) for b in bits])), any_node_rendered
+
+class IfNotEmptyNode(Node):
+    child_nodelists = ('nodelist_empty', 'nodelist_not_empty')
+
+    def __init__(self, nodelist_empty, nodelist_not_empty):
+        self.nodelist_empty = nodelist_empty
+        self.nodelist_not_empty = IfNotEmptyNodeList(nodelist_not_empty)
+
+    def render(self, context):
+        content, any_node_rendered = self.nodelist_not_empty.render_conditionally(context)
+        if any_node_rendered:
+            return content
+        if self.nodelist_empty:
+            return self.nodelist_empty.render(context)
+        return ''
+
 class IfEqualNode(Node):
     child_nodelists = ('nodelist_true', 'nodelist_false')
 
@@ -960,6 +991,39 @@
     return IfChangedNode(nodelist_true, nodelist_false, *values)
 
 @register.tag
+def ifnotempty(parser, token):
+    """
+    Renders only if at least one variable or template tag within also renders.
+
+    This allows a variable or template tag to be surrounded by markup, with
+    the markup omitted if the variable or template tag does not render.
+
+    An `{% else %}` block may also be used.
+
+    In the following example, the section will not be rendered unless another
+    template extends this one and overrides the `more_information` block::
+
+        {% ifnotempty %}
+            <section>
+                <h1>More information</h1>
+                {% block more_information %}{% endblock %}
+            </section>
+        {% endifnotempty %}
+
+    """
+    bits = token.contents.split()
+    if len(bits) != 1:
+        raise TemplateSyntaxError("ifnotempty takes no arguments")
+    nodelist_not_empty = parser.parse(('else', 'endifnotempty'))
+    token = parser.next_token()
+    if token.contents == 'else':
+        nodelist_empty = parser.parse(('endifnotempty',))
+        parser.delete_first_token()
+    else:
+        nodelist_empty = NodeList()
+    return IfNotEmptyNode(nodelist_empty, nodelist_not_empty)
+
+@register.tag
 def ssi(parser, token):
     """
     Outputs the contents of a given file into the page.
