Reputation: 974
I have following model admin. I'm displaying custom field in list view.
class CustomerAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email', 'state')
search_fields = ('first_name', 'last_name', 'email')
list_filter = ('state',)
def state(self, obj):
address = Address.objects.filter(owner=obj.id)
if address:
return address.state
return None
I tried above but it gives an error "list_filter[0]' refers to 'state' which does not refer to a Field." So I want filter records by state. So how I can do this in django 1.5?
Upvotes: 19
Views: 4014
Reputation: 33
list_filter works on related models.
If model looks like that:
class Address(models.Model):
owner = models.OneToOneField(Customer, models.CASCADE,
related_name='address')
state = models.CharField(max_length=20)
You can use address__state in ModelAdmin. For example:
@admin.register(Customer)
class CustomerAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email', 'state')
search_fields = ('first_name', 'last_name', 'email')
list_filter = ('address__state', )
Note that list_display doesn't work this way!
Upvotes: 1
Reputation: 36
Unfortunately this is not possible. In django.admin.views
, when collecting filter fields happens this:
if not isinstance(field, Field):
field_path = field
field = get_fields_from_path(self.model, field_path)[-1]
So, state
is not a Field
instance, but a function that returns string or None. Then as you can see, Django tries to add fields to list_filter
anyway, assuming it is not a Field
instance, but can be path to model field.
Eventually it adds state
to list_filter
, and then goes to django.db.models.options.Options
to retrieve instance of field.
try:
# Retrieve field instance by name from cached or just-computed
# field map.
return self.fields_map[field_name]
except KeyError:
raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))
As you see, Django can not see this field in model and throws an Exception. This Exception is handled by django.core.management.base.BaseCommand
, that converts error message to "list_filter[0]' refers to 'state' which does not refer to a Field."
Upvotes: 0
Reputation: 8029
class CustomerAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email', 'state')
list_filter = ('state',)
search_fields = ('first_name', 'last_name', 'email')
def state(self, obj):
address = Address.objects.filter(owner=obj.id)
if address:
return address.state
return None
You should include list_filter if you want to filter
Upvotes: -4