Поиск через sphinx в django 1.6 admin

от автора

Задача: реализовать полнотекстовый поиск в админке django.
Пример модели, по которой будем делать поиск:

class Movie(models.Model):     title_en = models.CharField(max_length=255, null=True)     title_ru = models.CharField(max_length=255, null=True) 

Установка и настройка sphinx

Ставим sphinx через любой пакетный менеджер, у меня под рукой только FreeBSD, поэтому я ставлю из портов.

cd /usr/ports/textproc/sphinxsearch make install clean 

В статье используется версия 0.9.9, с ней точно будет работать пакет django-sphinx, на других версиях не проверял.
Создаем конфиг /usr/local/etc/sphinx.conf

Скрытый текст

# Источник source movies_src {     type = pgsql # или mysql     sql_host = 127.0.0.1     sql_user = sphinx     sql_pass = sphinxpass     sql_db = dbname     sql_port = 5432     sql_query = select id, title_en, title_ru, year from movies_movie # запрос, который выбирает данные для индекса     sql_attr_uint = year }  # Настройки индекса index movies {     source = movies_src     path = /var/data/search/movies     docinfo = extern     charset_type = utf-8     morphology = stem_enru # подключаем русскую и английскую морфологию }  # Настройки демона searchd {     listen = 9312     log = /var/log/searchd.log     query_log = /var/log/searchd.query.log     read_timeout = 3     client_timeout = 10     max_children = 15     pid_file = /var/run/sphinxsearch/searchd.pid     max_matches = 1000     seamless_rotate = 1     preopen_indexes = 1     unlink_old = 1     mva_updates_pool = 1M     max_packet_size = 8M } 

Создаем лог-файлы и директории из конфига, делаем им chown _sphinx. Если вы тоже используете postgres не забудьте добавить соответствующую строчку в pg_hba.conf, чтобы сфинкс смог подключиться.
Выдаем юзеру права на чтение из нужной нам таблицы. Привожу пример для постгреса, чтобы не гуглить лишний раз:

GRANT CONNECT ON DATABASE mydb TO sphinx; GRANT USAGE ON SCHEMA public TO sphinx; GRANT SELECT ON movies_movie TO sphinx; 

Запускаем индексатор и ставим его в крон

/usr/local/bin/indexer --config /usr/local/etc/sphinx.conf  --rotate --all >/dev/null 2>&1 

Запускаем sphinx

/usr/local/etc/rc.d/sphinxsearch start 

Интеграция с django

Ставим пакет django-sphinx

pip install django-sphinx 

Добавляем ‘djangosphinx’ в INSTALLED_APPS
Прописываем настройки в settings.py

SPHINX_API_VERSION = 0x116 # для sphinx 0.9.9+ SPHINX_PORT = 9312 SPHINX_SERVER = '127.0.0.1' 

Добавляем в модель Sphinx-менеджер

class Movie(models.Model):     search = SphinxSearch(         index='movies',         weights={             'title_en': 100,             'title_ru': 100,         }     ) 

Проверяем что полнотекстовый поиск работает.

>>> Movie.search.query(u'зеленый').order_by('year')[0] <Movie: The Green Mile (1999) - Зеленая миля> 

Поиск через sphinx в админке

У django-sphinx как бы есть свой класс SphinxModelAdmin, который позволяет использовать сфинкс в штатном поиске админки.
Но вот что пишет сам автор про эту фичу:

  • Only shows your max sphinx results (defaults to 1000)
  • Filters currently don’t work.
  • This is a huge hack, so it may or may not continue working when Django updates.

Такое нам не подходит, так что придется допиливать.
В django 1.6 у класса ModelAdmin появился метод get_search_results, позволяющий переопределить встроенный механизм поиска.
Документация: docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_search_results
Его и будем использовать.
У меня получился такой класс:

class SphinxModelAdmin(admin.ModelAdmin):     def get_search_results(self, request, queryset, search_term):         if search_term:             sphinx_queryset = self.model.search.query(search_term)             doc_ids = [doc.pk for doc in sphinx_queryset]             queryset = queryset.filter(pk__in=doc_ids)             return queryset, True         else:             return super(SphinxModelAdmin, self).get_search_results(                 request, queryset, search_term             ) 

Этот способ не теряет фильтры и сортировки админки, мы просто сужаем область поиска до документов, найденных в сфинксе.

Использовать так:

class MovieAdmin(SphinxModelAdmin):     pass 

Проверяем что поиск правильно работает.

Внешний вид — django-grappelli

Минусы данного решения:
Django 1.6 на момент написания топика находится в бете.

Ссылочки:
sphinxsearch.com/
github.com/dcramer/django-sphinx
vostryakov.ru/blog/28-sphinx-11-django-postgresql/
docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_search_results

ссылка на оригинал статьи http://habrahabr.ru/post/188242/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *