diff --git a/AUTHORS b/AUTHORS index d34e882494..fb299a9e3b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -72,6 +72,7 @@ answer newbie questions, and generally made Django that much better: junzhang.jn@gmail.com Russell Keith-Magee Garth Kidd + kilian Sune Kirkeby Cameron Knight (ckknight) Bruce Kroeze diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py index 0e550dd471..3537f46755 100644 --- a/django/contrib/admin/templatetags/admin_list.py +++ b/django/contrib/admin/templatetags/admin_list.py @@ -165,7 +165,8 @@ def items_for_result(cl, result): result_repr = escape(str(field_val)) if result_repr == '': result_repr = ' ' - 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) diff --git a/django/core/management.py b/django/core/management.py index a2bacdcc48..eccd356ad7 100644 --- a/django/core/management.py +++ b/django/core/management.py @@ -936,6 +936,19 @@ def get_validation_errors(outfile, app=None): 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.') diff --git a/django/db/models/options.py b/django/db/models/options.py index 46a321f170..ff0d112d16 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -199,12 +199,13 @@ class Options(object): 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 diff --git a/docs/model-api.txt b/docs/model-api.txt index 0dc98416a3..c4d57bf8c4 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -1225,6 +1225,33 @@ A few special cases to note about ``list_display``: return self.birthday.strftime('%Y')[:3] + "0's" decade_born_in.short_description = 'Birth decade' +``list_display_links`` +---------------------- + +Set ``list_display_links`` to control which fields in ``list_display`` should +be linked to the "change" page for an object. + +By default, the change list page will link the first column -- the first field +specified in ``list_display`` -- to the change page for each item. But +``list_display_links`` lets you change which columns are linked. Set +``list_display_links`` to a list or tuple of field names (in the same format as +``list_display``) to link. + +``list_display_links`` can specify one or many field names. As long as the +field names appear in ``list_display``, Django doesn't care how many (or how +few) fields are linked. The only requirement is: If you want to use +``list_display_links``, you must define ``list_display``. + +In this example, the ``first_name`` and ``last_name`` fields will be linked on +the change list page:: + + class Admin: + list_display = ('first_name', 'last_name', 'birthday') + list_display_links = ('first_name', 'last_name') + +Finally, note that in order to use ``list_display_links``, you must define +``list_display``, too. + ``list_filter`` ---------------