Ticket #3400: list_filter.3.diff

File list_filter.3.diff, 4.4 KB (added by nick.lane.au@…, 13 years ago)

Improved patch per suggestions

  • django/contrib/admin/views/main.py

    === modified file 'django/contrib/admin/views/main.py'
     
    88from django.core.paginator import ObjectPaginator, InvalidPage
    99from django.shortcuts import get_object_or_404, render_to_response
    1010from django.db import models
    11 from django.db.models.query import handle_legacy_orderlist, QuerySet
     11from django.db.models.query import handle_legacy_orderlist, QuerySet, LOOKUP_SEPARATOR
    1212from django.http import Http404, HttpResponse, HttpResponseRedirect
    1313from django.utils.html import escape
    1414from django.utils.text import capfirst, get_text_list
     
    543543                               "admin/object_history.html"], extra_context, context_instance=template.RequestContext(request))
    544544history = staff_member_required(never_cache(history))
    545545
     546class FollowForeignKey(object):
     547    """
     548    A class to represent a ForeignKey that spans multiple foreign keys
     549    over multiple model classes.
     550    """
     551    def __init__(self, field, lookups):
     552        # Traverse the relationships to reach the final model class.
     553        for field_name in lookups[1:]:
     554            model = field.rel.to
     555            new_field = model._meta.get_field(field_name)
     556            if not new_field.rel: break
     557            field = new_field
     558        self.verbose_name = field.verbose_name
     559        self.rel = field.rel
     560        # Rejoin the lookups using the separator so that the
     561        # RelatedFilterSpec uses the correct lookup_kwarg.
     562        self.name = LOOKUP_SEPARATOR.join(lookups)
     563
    546564class ChangeList(object):
    547565    def __init__(self, request, model):
    548566        self.model = model
     
    574592    def get_filters(self, request):
    575593        filter_specs = []
    576594        if self.lookup_opts.admin.list_filter and not self.opts.one_to_one_field:
    577             filter_fields = [self.lookup_opts.get_field(field_name) \
    578                               for field_name in self.lookup_opts.admin.list_filter]
    579             for f in filter_fields:
     595            for field_name in self.lookup_opts.admin.list_filter:
     596                field_lookups = field_name.split(LOOKUP_SEPARATOR)
     597                f = self.lookup_opts.get_field(field_lookups[0])
     598                # If the field name spans multiple models, wrap the field in a
     599                # FollowForeignKey.
     600                if len(field_lookups) > 1 and f.rel:
     601                    f = FollowForeignKey(f, field_lookups)
    580602                spec = FilterSpec.create(f, request, self.params, self.model)
    581603                if spec and spec.has_output():
    582604                    filter_specs.append(spec)
  • django/core/management.py

    === modified file 'django/core/management.py'
     
    864864    from django.db import models, connection
    865865    from django.db.models.loading import get_app_errors
    866866    from django.db.models.fields.related import RelatedObject
     867    from django.db.models.query import LOOKUP_SEPARATOR
    867868
    868869    e = ModelErrorCollection(outfile)
    869870
     
    10141015                    e.add(opts, '"admin.list_filter", if given, must be set to a list or tuple.')
    10151016                else:
    10161017                    for fn in opts.admin.list_filter:
     1018                        # Break the entry up using the lookup separator, and
     1019                        # make sure each one points to a valid field.
     1020                        field_lookups = fn.split(LOOKUP_SEPARATOR)
    10171021                        try:
    1018                             f = opts.get_field(fn)
     1022                            f = opts.get_field(field_lookups[0])
     1023                            if len(field_lookups) > 1:
     1024                                if not f.rel:
     1025                                    e.add(opts, '"admin.list_filter" refers to %r, which contains a non-related field.' % fn)
     1026                                for field_name in field_lookups[1:]:
     1027                                    model = f.rel.to
     1028                                    f = model._meta.get_field(field_name)
     1029                                    if not f.rel:
     1030                                        e.add(opts, '"admin.list_filter" refers to %r, which contains a non-related field.' % fn)
    10191031                        except models.FieldDoesNotExist:
    10201032                            e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
    10211033                # date_hierarchy
Back to Top