Created
May 8, 2017 23:28
-
-
Save YellowSharkMT/46477c2e525d972c44dd7dc424ea8309 to your computer and use it in GitHub Desktop.
Customize Django's admin search results view to optionally show a column, with highlighted search term in the results.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This is a fairly specific use-case, where we wanted to search columns on a related model, and present those results in a | |
sensible way. We wanted this column to only be present if the user is conducting a search, and we wanted to customize the | |
output to make the search term prominent in the results. | |
""" | |
import re | |
from django.contrib.admin import ModelAdmin | |
from django.utils import formats | |
from django.utils.safestring import mark_safe | |
class WriterAdmin(ModelAdmin): | |
# correspondencelog is a related model, notes is a field on that model. | |
search_fields = ('username', 'correspondencelog__notes') | |
list_display = ('id', 'username',) | |
# creates a dynamic function that can be used by the WriterAdmin to populate a column with request-specific content | |
def make_get_notes_function(self, query): | |
# this is used to wrap the search term in <b> tags... | |
search_exp = re.compile('(' + query + ')', re.IGNORECASE) | |
replace_exp = r'<b>\1</b>' | |
# this function will get attached to the WriterAdmin, as self.get_notes | |
def get_notes(obj): | |
matching_notes = obj.correspondencelog_set.filter(notes__contains='{}'.format(query)) | |
# not a fan of this, would be cooler to use Django's template/context stuff... | |
notes_text = '' | |
notes_text_tpl = u'<span class="small date" title="{}">[{}]</span> {}<br/>' | |
for note in matching_notes: | |
short_date_string = formats.date_format(note.logged_at, 'SHORT_DATE_FORMAT') | |
long_date_string = formats.date_format(note.logged_at, 'DATETIME_FORMAT') | |
formatted_note = re.sub(search_exp, replace_exp, note.notes) | |
# gah, lots of .format(), sorry... | |
meta_text = u'By {} at {}'.format(note.logged_by.get_full_name(), long_date_string) | |
notes_text += notes_text_tpl.format(meta_text, short_date_string, formatted_note) | |
notes_text = notes_text[:-5] # trim off trailing '<br/>', yech... | |
return mark_safe(notes_text) | |
return get_notes | |
# This function is called early in the request process, and is our hook to update the ModelAdmin on-the-fly... | |
def changelist_view(self, request, extra_context=None): | |
# in this case, we want to customize the search results view... | |
if request.GET.get('q', None): | |
# update the self.list_display_value... | |
self.list_display = self.list_display + ('get_notes',) | |
# create the function that populates the column... | |
self.get_notes = self.make_get_notes_function(request.GET['q']) | |
self.get_notes.short_description = 'Notes' | |
return super(WriterAdmin, self).changelist_view(request, extra_context) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment