27

I want to add a filter in an admin changelist by a property of a foreign key, e.g.

class Address(model.Models):
    street = models.CharField(max_length=25)        
    city = models.CharField(max_length=25)
    country = models.CharField(max_length=25)        

class Customer(models.Model):
    name = models.CharField(max_length=25)
    address = models.ForeignKey(Address)

Let's say in the Customer admin changelist I want to show a filter by city and country (so show me all customers in a particular country or city).

But the standard list_filter() functionality seems to only allow filtering by fields directly on the model and not on any of its foreign key. I've tried:

list_filter = ("address__country",)

or

list_filter = ("address.country",)

but I always get the same type of error:

 'address__country' is not a callable or an attribute 

Any suggestions would be welcome. Is there some special naming convention/syntax to allow filtering on FK properties?

Jacek Furmankiewicz
  • 1,143
  • 1
  • 13
  • 22

3 Answers3

27

See https://code.djangoproject.com/ticket/3400 . It works ok in django 1.3 :)

class Room(models.Model):
    house = models.ForeignKey(House)

    def __unicode__(self):
        return self.house.town.name

class Booking(models.Model):
    room = models.ForeignKey(Room)

    def __unicode__(self):
        return self.room.house.town.name

class BookingOpts(admin.ModelAdmin):
    list_filter = ('room__house__town',)
    raw_id_admin = ('room', )

admin.site.register(Town)
admin.site.register(House)
admin.site.register(Room)
admin.site.register(Booking, BookingOpts)
luc
  • 41,928
  • 25
  • 127
  • 172
  • Nice suggestion, it works smoothly on Django 1.3.3, thank you. Obvious note: the first and the second classes go to models.py and the last one with the register functions go to admin.py. rooms__house__town is translated into rooms.house.town. – chirale Sep 05 '12 at 15:50
  • 1
    I just found this solution for a similar problem. If you need more power in your filter, look into extending django.contrib.admin.SimpleListFilter and rolling your own filter. I just did it for my new project, and it's much easier than it looked at first. – Hovis Biddle Nov 29 '12 at 06:17
  • 1
    Just to point out that this still works with Django 3.1.11 – Mohiuddin Sumon Feb 24 '22 at 19:00
1

I have found and tested following solution:

http://www.djangosnippets.org/snippets/1911/

It works with ForeignKeys, but it doesn't work with ManyToMany relations.

Dominik Szopa
  • 1,909
  • 1
  • 15
  • 16
0

I ran into the same problem and really needed a solution. I have a workaround that lets you create a filter on a FK related model property. You can even traverse more than one FK relationship. It creates a new FilterSpec subclass that subclasses the default RelatedFilterSpec used to give you a filter on a ForeignKey field.

See http://djangosnippets.org/snippets/2260/

OverClocked
  • 1,177
  • 1
  • 11
  • 19