Ticket #3397: patch_allow_ordering_by_nonfields.diff

File patch_allow_ordering_by_nonfields.diff, 5.2 KB (added by marcink@…, 13 years ago)

Diff against trunk

  • django/contrib/admin/templatetags/admin_list.py

     
    8484                    header = attr.short_description
    8585                except AttributeError:
    8686                    header = field_name.replace('_', ' ')
    87             # Non-field list_display values don't get ordering capability.
    88             yield {"text": header}
     87
     88            # It is a non-field, but perhaps one that is sortable
     89            if not getattr(getattr(cl.model, field_name), "admin_order_field", None):
     90                yield {"text": header}
     91                continue
     92
     93            # So this _is_ a sortable non-field.  Go to the yield
     94            # after the else clause.
    8995        else:
    9096            if isinstance(f.rel, models.ManyToOneRel) and f.null:
    9197                yield {"text": f.verbose_name}
     98                continue
    9299            else:
    93                 th_classes = []
    94                 new_order_type = 'asc'
    95                 if field_name == cl.order_field:
    96                     th_classes.append('sorted %sending' % cl.order_type.lower())
    97                     new_order_type = {'asc': 'desc', 'desc': 'asc'}[cl.order_type.lower()]
     100                header = f.verbose_name
    98101
    99                 yield {"text": f.verbose_name,
    100                        "sortable": True,
    101                        "url": cl.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),
    102                        "class_attrib": (th_classes and ' class="%s"' % ' '.join(th_classes) or '')}
     102        th_classes = []
     103        new_order_type = 'asc'
     104        if field_name == cl.order_field:
     105            th_classes.append('sorted %sending' % cl.order_type.lower())
     106            new_order_type = {'asc': 'desc', 'desc': 'asc'}[cl.order_type.lower()]
    103107
     108        yield {"text": header,
     109               "sortable": True,
     110               "url": cl.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),
     111               "class_attrib": (th_classes and ' class="%s"' % ' '.join(th_classes) or '')}
     112
    104113def _boolean_icon(field_val):
    105114    BOOLEAN_MAPPING = {True: 'yes', False: 'no', None: 'unknown'}
    106115    return '<img src="%simg/admin/icon-%s.gif" alt="%s" />' % (settings.ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val)
  • django/contrib/admin/views/main.py

     
    655655            order_field, order_type = ordering[0], 'asc'
    656656        if params.has_key(ORDER_VAR):
    657657            try:
     658                field_name = lookup_opts.admin.list_display[int(params[ORDER_VAR])]
    658659                try:
    659                     f = lookup_opts.get_field(lookup_opts.admin.list_display[int(params[ORDER_VAR])])
     660                    f = lookup_opts.get_field(field_name)
    660661                except models.FieldDoesNotExist:
    661                     pass
     662                    # see if field_name is a name of a non-field
     663                    # that allows sorting
     664                    try:
     665                        attr = getattr(lookup_opts.admin.manager.model, field_name)
     666                        order_field = attr.admin_order_field
     667                    except IndexError:
     668                        pass
    662669                else:
    663670                    if not isinstance(f.rel, models.ManyToOneRel) or not f.null:
    664671                        order_field = f.name
  • docs/model-api.txt

     
    12951295
    12961296          list_display = ('__str__', 'some_other_field')
    12971297
    1298     * For any element of ``list_display`` that is not a field on the model, the
    1299       change list page will not allow ordering by that column. This is because
    1300       ordering is done at the database level, and Django has no way of knowing
    1301       how to order the result of a custom method at the SQL level.
     1298    * For any element of ``list_display`` that is not a field on the
     1299      model, you can specify the actual field that should be used to
     1300      order the list in that element's ``admin_order_field``
     1301      attribute.  If you don't, then the change list page will not
     1302      allow ordering by that column. This is because ordering is done
     1303      at the database level, and Django has no way of knowing how to
     1304      order the result of a custom method at the SQL level.
    13021305
     1306      Here's a full example model::
     1307
     1308          class Person(models.Model):
     1309              first_name = models.CharField(maxlength=50)
     1310              color_code = models.CharField(maxlength=6)
     1311
     1312              class Admin:
     1313                  list_display = ('first_name', 'colored_first_name')
     1314
     1315              def colored_first_name(self):
     1316                  return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
     1317              colored_first_name.allow_tags = True
     1318              colored_first_name.admin_order_field = 'first_name'
     1319
     1320
    13031321``list_display_links``
    13041322----------------------
    13051323
Back to Top