Index: django/db/models/options.py
===================================================================
--- django/db/models/options.py	(revision 3278)
+++ django/db/models/options.py	(working copy)
@@ -199,12 +199,13 @@
         return self._field_types[field_type]
 
 class AdminOptions(object):
-    def __init__(self, fields=None, js=None, list_display=None, list_filter=None,
+    def __init__(self, fields=None, js=None, list_display=None, list_display_links=None, list_filter=None,
         date_hierarchy=None, save_as=False, ordering=None, search_fields=None,
         save_on_top=False, list_select_related=False, manager=None, list_per_page=100):
         self.fields = fields
         self.js = js or []
         self.list_display = list_display or ['__str__']
+        self.list_display_links = list_display_links or []
         self.list_filter = list_filter or []
         self.date_hierarchy = date_hierarchy
         self.save_as, self.ordering = save_as, ordering
Index: django/core/management.py
===================================================================
--- django/core/management.py	(revision 3278)
+++ django/core/management.py	(working copy)
@@ -936,6 +936,19 @@
                         else:
                             if isinstance(f, models.ManyToManyField):
                                 e.add(opts, '"admin.list_display" doesn\'t support ManyToManyFields (%r).' % fn)
+                # list_display_links
+                if opts.admin.list_display_links and not opts.admin.list_display:
+                    e.add(opts, '"admin.list_display" must be defined for "admin.list_display_links" to be used.')
+                if not isinstance(opts.admin.list_display_links, (list, tuple)):
+                    e.add(opts, '"admin.list_display_links", if given, must be set to a list or tuple.')
+                else:
+                    for fn in opts.admin.list_display_links:
+                        try:
+                            f = opts.get_field(fn)
+                        except models.FieldDoesNotExist:
+                            e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
+                        if fn not in opts.admin.list_display:
+                            e.add(opts, '"admin.list_display_links" refers to %r, which is not defined in "admin.list_display".' % fn)
                 # list_filter
                 if not isinstance(opts.admin.list_filter, (list, tuple)):
                     e.add(opts, '"admin.list_filter", if given, must be set to a list or tuple.')
Index: django/contrib/admin/templatetags/admin_list.py
===================================================================
--- django/contrib/admin/templatetags/admin_list.py	(revision 3278)
+++ django/contrib/admin/templatetags/admin_list.py	(working copy)
@@ -165,7 +165,8 @@
                 result_repr = escape(str(field_val))
         if result_repr == '':
             result_repr = '&nbsp;'
-        if first: # First column is a special case
+        # If list_display_links not defined, add the link tag to the first field
+        if (first and not cl.lookup_opts.admin.list_display_links) or field_name in cl.lookup_opts.admin.list_display_links: 
             first = False
             url = cl.url_for_result(result)
             result_id = str(getattr(result, pk)) # str() is needed in case of 23L (long ints)
