Commit 06b11b61 authored by Konrad Świat's avatar Konrad Świat Committed by Tim Graham
Browse files

Fixed #23616 - Fixed generic relations in ModelAdmin.list_filter.

Thanks ranjur for reporting bug, timgraham for review,
and collinanderson for contributing tips.
parent 466b38ea
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -417,7 +417,10 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
                    # since it's ignored in ChangeList.get_filters().
                    return True
                model = field.rel.to
                if hasattr(field.rel, 'get_related_field'):
                    rel_name = field.rel.get_related_field().name
                else:
                    rel_name = None
            elif isinstance(field, RelatedObject):
                model = field.model
                rel_name = model._meta.pk.name
+2 −0
Original line number Diff line number Diff line
@@ -113,3 +113,5 @@ Bugfixes
* Added a prompt to the migrations questioner when removing the null constraint
  from a field to prevent an IntegrityError on existing NULL rows
  (:ticket:`23609`).

* Fixed generic relations in ``ModelAdmin.list_filter`` (:ticket:`23616`).
+22 −0
Original line number Diff line number Diff line
from __future__ import unicode_literals

from django.contrib.auth.models import User
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils.encoding import python_2_unicode_compatible

@@ -35,3 +37,23 @@ class Employee(models.Model):

    def __str__(self):
        return self.name


@python_2_unicode_compatible
class TaggedItem(models.Model):
    tag = models.SlugField()
    content_type = models.ForeignKey(ContentType, related_name='tagged_items')
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    def __str__(self):
        return self.tag


@python_2_unicode_compatible
class Bookmark(models.Model):
    url = models.URLField()
    tags = GenericRelation(TaggedItem)

    def __str__(self):
        return self.url
+23 −1
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@ from django.test import TestCase, RequestFactory, override_settings
from django.utils.encoding import force_text
from django.utils import six

from .models import Book, Department, Employee
from .models import Book, Department, Employee, Bookmark, TaggedItem


def select_by(dictlist, key, value):
@@ -205,6 +205,10 @@ class DepartmentFilterDynamicValueBookAdmin(EmployeeAdmin):
    list_filter = [DepartmentListFilterLookupWithDynamicValue, ]


class BookmarkAdminGenericRelation(ModelAdmin):
    list_filter = ['tags__tag']


class ListFiltersTests(TestCase):

    def setUp(self):
@@ -539,6 +543,24 @@ class ListFiltersTests(TestCase):
        expected = [(self.bob.pk, 'bob'), (self.lisa.pk, 'lisa')]
        self.assertEqual(sorted(filterspec.lookup_choices), sorted(expected))

    def test_listfilter_genericrelation(self):
        django_bookmark = Bookmark.objects.create(url='https://www.djangoproject.com/')
        python_bookmark = Bookmark.objects.create(url='https://www.python.org/')
        kernel_bookmark = Bookmark.objects.create(url='https://www.kernel.org/')

        TaggedItem.objects.create(content_object=django_bookmark, tag='python')
        TaggedItem.objects.create(content_object=python_bookmark, tag='python')
        TaggedItem.objects.create(content_object=kernel_bookmark, tag='linux')

        modeladmin = BookmarkAdminGenericRelation(Bookmark, site)

        request = self.request_factory.get('/', {'tags__tag': 'python'})
        changelist = self.get_changelist(request, Bookmark, modeladmin)
        queryset = changelist.get_queryset(request)

        expected = [python_bookmark, django_bookmark]
        self.assertEqual(list(queryset), expected)

    def test_booleanfieldlistfilter(self):
        modeladmin = BookAdmin(Book, site)
        self.verify_booleanfieldlistfilter(modeladmin)