Django: list_filter and foreign key fields

Viewed 26707

Django doesn't support getting foreign key values from list_display or list_filter (e.g foo__bar). I know you can create a module method as a workaround for list_display, but how would I go about to do the same for list_filter? Thanks.

7 Answers

Well, the docs say that you can may use ForeignKey field types in list_filter:

http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter

An example:

# models.py:
class Foo(models.Model):
    name = models.CharField(max_length=255)

    def __unicode__(self):
        return self.name

class Bar(models.Model):
    name = models.CharField(max_length=255)
    foo = models.ForeignKey(Foo)

# admin.py:
class BarAdmin(admin.ModelAdmin):
    list_filter = ('foo')

If you want to filter by a field from the related model, there's a patch on the way to make this work (will probably be merged into 1.2 as it seems):

http://code.djangoproject.com/ticket/3400

If you construct the URL for the changelist manually then Django has no problems following relationships. For example:

/admin/contact/contact/?participant__event=8

or

/admin/contact/contact/?participant__event__name__icontains=er

Both work fine (although the latter doesn't add 'distinct()' so might have duplicates but that won't usually be an issue for filters)

So you just need to add something to the page that creates the correct links. You can do this either with by overriding the changelist template or by writing a custom filterspec. There are several examples I found by Googling - particularly on Django Snippets

The Haes answer works perfectly, but if the __ looks up to another ForeignKey field, you end up with a blank result. You must place another __ lookup, until it points to the real field.

In my case: list_filter = ('place__condo__name', )

my models.py:

class Condo(models.Model):
    name = models.CharField(max_length=70)
    ...

class Place(models.Model):
    condo = models.ForeignKey(Condo)
    ...

class Actions(models.Model):
    place = models.ForeignKey(Place)
    ...
Related