debian-django-watson/watson/admin.py

79 lines
2.9 KiB
Python

"""Admin integration for django-watson."""
from __future__ import unicode_literals
from django.contrib import admin
from django.contrib.admin.views.main import ChangeList
from watson.search import SearchEngine, SearchAdapter
admin_search_engine = SearchEngine("admin")
class WatsonSearchChangeList(ChangeList):
"""A change list that takes advantage of django-watson full text search."""
def get_queryset(self, *args, **kwargs):
"""Creates the query set."""
# Do the basic searching.
search_fields = self.search_fields
self.search_fields = ()
try:
qs = super(WatsonSearchChangeList, self).get_queryset(*args, **kwargs)
finally:
self.search_fields = search_fields
# Do the full text searching.
if self.query.strip():
qs = self.model_admin.search_engine.filter(qs, self.query, ranking=False)
return qs
class SearchAdmin(admin.ModelAdmin):
"""
A ModelAdmin subclass that provides full-text search integration.
Subclass this admin class and specify a tuple of search_fields for instant
integration!
"""
search_engine = admin_search_engine
search_adapter_cls = SearchAdapter
@property
def search_context_manager(self):
"""The search context manager used by this SearchAdmin."""
return self.search_engine._search_context_manager
def __init__(self, *args, **kwargs):
"""Initializes the search admin."""
super(SearchAdmin, self).__init__(*args, **kwargs)
# Check that the search fields are valid.
for search_field in self.search_fields or ():
if search_field[0] in ("^", "@", "="):
raise ValueError("SearchAdmin does not support search fields prefixed with '^', '=' or '@'")
# Register with the search engine.
self.register_model_with_watson()
# Set up revision contexts on key methods, just in case.
self.add_view = self.search_context_manager.update_index()(self.add_view)
self.change_view = self.search_context_manager.update_index()(self.change_view)
self.delete_view = self.search_context_manager.update_index()(self.delete_view)
self.changelist_view = self.search_context_manager.update_index()(self.changelist_view)
def register_model_with_watson(self):
"""Registers this admin class' model with django-watson."""
if not self.search_engine.is_registered(self.model) and self.search_fields:
self.search_engine.register(
self.model,
fields=self.search_fields,
adapter_cls=self.search_adapter_cls,
get_live_queryset=lambda self_: None, # Ensure complete queryset is used in admin.
)
def get_changelist(self, request, **kwargs):
"""Returns the ChangeList class for use on the changelist page."""
return WatsonSearchChangeList