Index: core/template/defaulttags.py
===================================================================
--- core/template/defaulttags.py	(revision 1489)
+++ core/template/defaulttags.py	(working copy)
@@ -179,6 +179,35 @@
                 return self.nodelist_true.render(context)
         return self.nodelist_false.render(context)
 
+class RandomNode(Node):
+    def __init__(self, nodelist_options, weights=None):
+        self.nodelist_options = nodelist_options
+        self.weights = weights
+        if weights:
+            self.weight_total = 0
+            self.weight_items = {}
+            for i, option in enumerate(nodelist_options):
+                self.weight_total += weights[i]
+                self.weight_items[self.weight_total] = option
+            self.weight_boundaries = self.weight_items.keys()
+            self.weight_boundaries.sort()
+
+    def render(self, context):
+        if self.weights:
+            from bisect import bisect_right
+            from random import randint
+            return self.weight_items[
+                        self.weight_boundaries[
+                            bisect_right(
+                                self.weight_boundaries,
+                                randint(0, self.weight_total - 1)
+                                )
+                            ]
+                        ].render(context)
+        else:
+            from random import choice
+            return choice(self.nodelist_options).render(context)
+
 class RegroupNode(Node):
     def __init__(self, target, expression, var_name):
         self.target, self.expression = target, expression
@@ -598,6 +627,68 @@
 ifchanged = register.tag(ifchanged)
 
 #@register.tag
+def random(parser, token):
+    """
+    Output the contents of a random block, with optional weighting.
+
+    The `random` block tag must contain one or more `or` tags, which separate
+    possible choices; a choice in this context is everything between a
+    `random` and `or` tag, between two `or` tags, or between an `or` and an
+    `endrandom` tag.
+
+    Sample usage::
+
+        {% random %}
+        You will see me half the time.
+        {% or %}
+        You will see me the other half.
+        {% endrandom %}
+
+    To specify optional weights for the items, include comma-separated integers
+    in the `random` tag, one for each item in order, like so::
+
+        {% random 4,1 %}
+        You will see me four times more often than the other option.
+        {% or %}
+        You will see me only one-fifth of the time.
+        {% endrandom %}
+
+    The chance of a weighted item being shown is its weight value divided by
+    the total of all weight values.
+    """
+    args = token.contents.split()
+    if len(args) == 1:
+        # {% random %}
+        weights = None
+    elif len(args) == 2 and ',' in args[1]:
+        # {% random 4,2,1 %}
+        try:
+            weights = [int(w) for w in args[1].split(',') if w]
+        except ValueError:
+            raise TemplateSyntaxError("Weight arguments for 'random' must be integers")
+        for w in weights:
+            if w < 1:
+                raise TemplateSyntaxError("Weight arguments must be positive integers")
+    else:
+        raise TemplateSyntaxError("Invalid arguments to 'random': %s" % args)
+    options = NodeList()
+    while True:
+        option = parser.parse(('or', 'endrandom'))
+        token = parser.next_token()
+        options.append(option)
+        if token.contents == 'or':
+            continue
+        parser.delete_first_token()
+        break
+    if len(options) < 2:
+        raise TemplateSyntaxError, "'random' tag must have at least two possibilities"
+    elif weights and len(options) != len(weights):
+        raise TemplateSyntaxError, "The number of specified weights (%s)" \
+                " must equal the number of possible options (%s)" % (len(options), len(weights))
+    return RandomNode(options, weights=weights)
+do_random = register.tag("random", random)
+
+#@register.tag
 def ssi(parser, token):
     """
     Output the contents of a given file into the page.
