diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py
index 220b60e..d2338eb 100644
--- a/django/contrib/admin/templatetags/admin_list.py
+++ b/django/contrib/admin/templatetags/admin_list.py
@@ -110,9 +110,9 @@ 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()]
+        if field_name == cl.order_field[0] or admin_order_field == cl.order_field[0]:
+            th_classes.append('sorted %sending' % cl.order_type[0].lower())
+            new_order_type = {'asc': 'desc', 'desc': 'asc'}[cl.order_type[0].lower()]
 
         yield {
             "text": header,
diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
index 0b98f11..d34bd86 100644
--- a/django/contrib/admin/views/main.py
+++ b/django/contrib/admin/views/main.py
@@ -129,18 +129,31 @@ class ChangeList(object):
 
     def get_ordering(self):
         lookup_opts, params = self.lookup_opts, self.params
-        # For ordering, first check the "ordering" parameter in the admin
-        # options, then check the object's default ordering. If neither of
-        # those exist, order descending by ID by default. Finally, look for
-        # 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:
+        # For ordering, first check manually-specified ordering from the query
+        # string and let this override all other orderings. If there is no
+        # manually-specified ordering check the "ordering" parameter in the
+        # admin options, then check the object's default ordering. If neither
+        # of those exist, order descending by ID by default.
+
+        # Support multiple orderings by having order_field and order_type be
+        # lists such that order_field[i] and order_type[i] are corresponding
+        # order_field and order_type values.
+
+        order_field = []
+        order_type = []
+        # Check for manually-specified ordering from query string.
+        if ORDER_VAR in params and ORDER_TYPE_VAR in params:
             try:
+
+                # Get order_type. If order_type is not 'asc' or 'desc' then
+                # raise ValueError to 'get out' of try block and use default
+                # ordering.
+                if params[ORDER_TYPE_VAR] in ('asc', 'desc'):
+                    order_type.append(params[ORDER_TYPE_VAR])
+                else:
+                    raise ValueError
+
+                # Get order_field
                 field_name = self.list_display[int(params[ORDER_VAR])]
                 try:
                     f = lookup_opts.get_field(field_name)
@@ -154,15 +167,27 @@ class ChangeList(object):
                             attr = getattr(self.model_admin, field_name)
                         else:
                             attr = getattr(self.model, field_name)
-                        order_field = attr.admin_order_field
+                        order_field.append(attr.admin_order_field)
                     except AttributeError:
                         pass
                 else:
-                    order_field = f.name
+                    order_field.append(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]
+
+        if not order_field or not order_type:
+            # Get ordering from "ordering" parameter in the admin options,
+            # object's default ordering, or by ID descending.
+            ordering = self.model_admin.ordering or lookup_opts.ordering or ['-' + lookup_opts.pk.name]
+            for i in range(len(ordering)):
+                if ordering[i].startswith('-'):
+                    order_field.append(ordering[i][1:])
+                    order_type.append('desc')
+                else:
+                    order_field.append(ordering[i])
+                    order_type.append('asc')
+
         return order_field, order_type
 
     def get_query_set(self):
@@ -224,7 +249,9 @@ class ChangeList(object):
 
         # Set ordering.
         if self.order_field:
-            qs = qs.order_by('%s%s' % ((self.order_type == 'desc' and '-' or ''), self.order_field))
+            ordering = ['%s%s' % ((self.order_type[i] == 'desc' and '-' or ''),
+                self.order_field[i]) for i in range(len(self.order_field))]
+            qs = qs.order_by(*ordering)
 
         # Apply keyword searches.
         def construct_search(field_name):
