diff --git a/django/contrib/admin/media/css/base.css b/django/contrib/admin/media/css/base.css
index c5e385d..9a7a0f2 100644
--- a/django/contrib/admin/media/css/base.css
+++ b/django/contrib/admin/media/css/base.css
@@ -326,6 +326,20 @@ table thead th.descending a {
     background: url(../img/admin/arrow-down.gif) right .4em no-repeat;
 }
 
+table thead th.sorted a span.text {
+   display: block;
+   float: left;
+}
+table thead th.sorted a span.sort_pos {
+   display: block;
+   float: right;
+   font-size: .6em;
+}
+table thead th.sorted a span.clear{
+   display: block;
+   clear: both;
+}
+
 /* ORDERABLE TABLES */
 
 table.orderable tbody tr td:hover {
diff --git a/django/contrib/admin/templates/admin/change_list_results.html b/django/contrib/admin/templates/admin/change_list_results.html
index b3fa224..2fd44c8 100644
--- a/django/contrib/admin/templates/admin/change_list_results.html
+++ b/django/contrib/admin/templates/admin/change_list_results.html
@@ -8,10 +8,14 @@
 <table id="result_list">
 <thead>
 <tr>
-{% for header in result_headers %}<th scope="col"{{ header.class_attrib }}>
-{% if header.sortable %}<a href="{{ header.url }}">{% endif %}
-{{ header.text|capfirst }}
-{% if header.sortable %}</a>{% endif %}</th>{% endfor %}
+{% for header in result_headers %}
+<th scope="col" {{ header.class_attrib }}>
+  {% if header.sortable %}<a href="{{ header.url }}">{% endif %}
+  <span class="text">{{ header.text|capfirst }}</span>
+  {% if header.sortable %}<span class="sort_pos">{{ header.sort_pos }}</span>
+  <span class="clear"></span>
+  </a>{% endif %}
+</th>{% endfor %}
 </tr>
 </thead>
 <tbody>
diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py
index fdf082b..3b34091 100644
--- a/django/contrib/admin/templatetags/admin_list.py
+++ b/django/contrib/admin/templatetags/admin_list.py
@@ -110,14 +110,44 @@ def result_headers(cl):
 
         th_classes = []
         new_order_type = 'asc'
-        if field_name == cl.order_field or admin_order_field == cl.order_field:
-            th_classes.append('sorted %sending' % cl.order_type.lower())
-            new_order_type = {'asc': 'desc', 'desc': 'asc'}[cl.order_type.lower()]
+        ordering_fields = cl.get_ordering_fields()
+        sort_pos = ''
+        if field_name in ordering_fields.keys() or admin_order_field in ordering_fields.keys():
+            if not field_name in ordering_fields.keys():
+                field_name = admin_order_field
+            order_type = ordering_fields.get(field_name).lower()
+            sort_pos = ordering_fields.keys().index(field_name) + 1
+            th_classes.append('sorted %sending' % order_type)
+            new_order_type = {'':'asc', 'asc': 'desc', 'desc': ''}[order_type]
+
+        # build new ordering param
+        o_list = []
+        for f in ordering_fields.keys():
+            try:
+                n = cl.list_display.index(f)
+            except ValueError:
+                continue
+
+            if f == field_name:
+                if new_order_type == '':
+                    continue
+                t = new_order_type
+            else:
+                t = ordering_fields.get(f)
+
+            o_list.append((t=='desc' and '-' or '') + str(n))
+
+        if field_name not in ordering_fields.keys() and new_order_type:
+            n = cl.list_display.index(field_name)
+            o_list.append((new_order_type=='desc' and '-' or '') + str(n))
+
+        o_list = ','.join(o_list)
 
         yield {
             "text": header,
             "sortable": True,
-            "url": cl.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),
+            "sort_pos": sort_pos > 0 and len(ordering_fields) > 0 and unicode(sort_pos) or '',
+            "url": cl.get_query_string({ORDER_VAR: o_list}),
             "class_attrib": mark_safe(th_classes and ' class="%s"' % ' '.join(th_classes) or '')
         }
 
diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
index 170d168..b53806c 100644
--- a/django/contrib/admin/views/main.py
+++ b/django/contrib/admin/views/main.py
@@ -4,6 +4,8 @@ from django.contrib.admin.util import quote, get_fields_from_path
 from django.core.exceptions import SuspiciousOperation
 from django.core.paginator import InvalidPage
 from django.db import models
+from django.db.models.query import QuerySet
+from django.utils.datastructures import SortedDict
 from django.utils.encoding import force_unicode, smart_str
 from django.utils.translation import ugettext, ugettext_lazy
 from django.utils.http import urlencode
@@ -59,7 +61,7 @@ class ChangeList(object):
             self.list_editable = ()
         else:
             self.list_editable = list_editable
-        self.order_field, self.order_type = self.get_ordering()
+        self.ordering = self.get_ordering()
         self.query = request.GET.get(SEARCH_VAR, '')
         self.query_set = self.get_query_set()
         self.get_results(request)
@@ -136,35 +138,46 @@ class ChangeList(object):
         # manually-specified ordering from the query string.
         ordering = self.model_admin.ordering or lookup_opts.ordering or ['-' + lookup_opts.pk.name]
 
-        if ordering[0].startswith('-'):
-            order_field, order_type = ordering[0][1:], 'desc'
-        else:
-            order_field, order_type = ordering[0], 'asc'
         if ORDER_VAR in params:
-            try:
-                field_name = self.list_display[int(params[ORDER_VAR])]
+            # Clear ordering and used params
+            ordering = []
+            order_params = params[ORDER_VAR].split(',')
+            for p in order_params:
                 try:
-                    f = lookup_opts.get_field(field_name)
-                except models.FieldDoesNotExist:
-                    # See whether field_name is a name of a non-field
-                    # that allows sorting.
+                    none, pfx, idx = p.rpartition('-')
+                    field_name = self.list_display[int(idx)]
                     try:
-                        if callable(field_name):
-                            attr = field_name
-                        elif hasattr(self.model_admin, field_name):
-                            attr = getattr(self.model_admin, field_name)
-                        else:
-                            attr = getattr(self.model, field_name)
-                        order_field = attr.admin_order_field
-                    except AttributeError:
-                        pass
-                else:
-                    order_field = f.name
-            except (IndexError, ValueError):
-                pass # Invalid ordering specified. Just use the default.
-        if ORDER_TYPE_VAR in params and params[ORDER_TYPE_VAR] in ('asc', 'desc'):
-            order_type = params[ORDER_TYPE_VAR]
-        return order_field, order_type
+                        f = lookup_opts.get_field(field_name)
+                    except models.FieldDoesNotExist:
+                        # See whether field_name is a name of a non-field
+                        # that allows sorting.
+                        try:
+                            if callable(field_name):
+                                attr = field_name
+                            elif hasattr(self.model_admin, field_name):
+                                attr = getattr(self.model_admin, field_name)
+                            else:
+                                attr = getattr(self.model, field_name)
+                            field_name = attr.admin_order_field
+                        except AttributeError:
+                            pass
+                    else:
+                        field_name = f.name
+
+                    ordering.append(pfx + field_name)
+
+                except (IndexError, ValueError):
+                    pass # Invalid ordering specified. Skip it.
+
+        return ordering
+
+    def get_ordering_fields(self):
+        # Returns a SortedDict of ordering fields and asc/desc
+        ordering_fields = SortedDict()
+        for o in self.ordering:
+            none, t, f = o.rpartition('-')
+            ordering_fields[f] = t == '-' and 'desc' or 'asc'
+        return ordering_fields
 
     def get_query_set(self):
         use_distinct = False
@@ -239,8 +252,8 @@ class ChangeList(object):
                             break
 
         # Set ordering.
-        if self.order_field:
-            qs = qs.order_by('%s%s' % ((self.order_type == 'desc' and '-' or ''), self.order_field))
+        if self.ordering:
+            qs = qs.order_by(*self.ordering)
 
         # Apply keyword searches.
         def construct_search(field_name):
