📜 ⬆️ ⬇️

Search through sphinx in django 1.6 admin

Task: implement full-text search in django admin panel.
An example of a model by which we will search:
class Movie(models.Model): title_en = models.CharField(max_length=255, null=True) title_ru = models.CharField(max_length=255, null=True) year = models.PositiveSmallIntegerField(null=True) 


Install and configure sphinx


We install sphinx through any package manager, I only have FreeBSD at hand, so I install from ports.
 cd /usr/ports/textproc/sphinxsearch make install clean 

The article uses version 0.9.9, the django-sphinx package will work with it, it did not check on other versions.
Create a config /usr/local/etc/sphinx.conf
Hidden text
 #  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 } 


Create log files and directories from the config, make them chown _sphinx. If you are also using postgres, do not forget to add the appropriate line to pg_hba.conf so that the sphinx can connect.
We give the user read rights from the table we need. I give an example for postgres, so as not to google once again:
 GRANT CONNECT ON DATABASE mydb TO sphinx; GRANT USAGE ON SCHEMA public TO sphinx; GRANT SELECT ON movies_movie TO sphinx; 

Run the indexer and put it in kroner
 /usr/local/bin/indexer --config /usr/local/etc/sphinx.conf --rotate --all >/dev/null 2>&1 

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

Django integration


Put the package django-sphinx
 pip install django-sphinx 

Add 'djangosphinx' to INSTALLED_APPS
Register settings in settings.py
 SPHINX_API_VERSION = 0x116 #  sphinx 0.9.9+ SPHINX_PORT = 9312 SPHINX_SERVER = '127.0.0.1' 

Add Sphinx Manager to the model
 class Movie(models.Model): search = SphinxSearch( index='movies', weights={ 'title_en': 100, 'title_ru': 100, } ) 

We check that full-text search works.
 >>> Movie.search.query(u'').order_by('year')[0] <Movie: The Green Mile (1999) -  > 

Search through sphinx in admin panel


Django-sphinx seems to have its own SphinxModelAdmin class, which allows you to use Sphinx in a regular admin search.
But the author himself writes about this feature:

This does not suit us, so we'll have to finish it.
In django 1.6, the ModelAdmin class has a get_search_results method that allows you to override the built-in search engine.
Documentation: docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_search_results
We will use it.
I got this class:
 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 ) 

This method does not lose the filters and admin sorting, we just narrow the search to the documents found in the sphinx.

Use this:
 class MovieAdmin(SphinxModelAdmin): pass 

We check that the search works correctly.

Appearance - django-grappelli

Cons of this solution:
Django 1.6 at the time of this writing is in beta.
')
Link:
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

Source: https://habr.com/ru/post/188242/


All Articles