In the django admin you can add search fields. Very handy! You get a search field at the top of your admin page to quickly filter the results.
Here’s an example:
class InvitationAdmin(admin.ModelAdmin):
model = models.Invitation
list_display = ['email', 'name', 'is_activated', 'activated_on']
search_fields = ['name', 'email']
There is a mistake I often make: adding a foreignkey field in the
search_fields
list! Let’s take the standard django book/author
example. You have a Book
and an Author
model. Book
has a
foreignkey to Author
.
On the admin page that lists the books you want to have a search box. Not only for book titles, but you also want to search on authors’ names and get their books. Easy:
class BookAdmin(admin.ModelAdmin):
model = models.Book
list_display = ['title', 'isbn', 'num_pages', 'author']
search_fields = ['title, 'author']
Let’s try it out in the admin. Oops:
Traceback (most recent call last):
...
TypeError: Related Field got invalid lookup: icontains
You have to point at a proper texually-searchable field instead of directly to a model (via a ForeignKey field). It is easy to fix:
class BookAdmin(admin.ModelAdmin):
...
search_fields = ['title, 'author__name']
I’ve written a very simple test that tests all my ModelAdmin’s search_fields:
from django.test import TestCase
from myapp import admin
class TestSearchFields(TestCase):
def test_for_valid_search_fields(self):
# It is easy to add a foreignkey in a search field instead of a
# stringfield on the class the foreign key points to.
for model_admin_class in [
# Hardcoded list
admin.PortalAdmin,
admin.TokenAdmin,
admin.InvitationAdmin,
admin.UserProfileAdmin,
admin.RoleAdmin,
admin.OrganisationAdmin,
admin.OrganisationRoleAdmin]:
model_class = model_admin_class.model
print("Testing search fields for %s" % model_class)
for fieldname in model_admin_class.search_fields:
query = '%s__icontains' % fieldname
print("Testing with %s" % query)
kwargs = {query: 'reinout'}
# We have no content, so the number of results if we search on
# something should be zero. The only thing that matters is
# that we get no 'cannot search on foreignkey' error.
self.assertEquals(
model_class.objects.filter(**kwargs).count(),
0)
Works like a charm! It immediately reported an error in one of my
search_fields
:-)
Note: I rely on print()
to tell me what went wrong. Which works, as I use
nose as a test runner, which suppresses the output unless the test fails.
My name is Reinout van Rees and I work a lot with Python (programming language) and Django (website framework). I live in The Netherlands and I'm happily married to Annie van Rees-Kooiman.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):