The perfect starting point to integrate Algolia within your Django project
Documentation • Community Forum • Stack Overflow • Report a bug • FAQ • Support
You can find the full reference on Algolia's website.
This package lets you easily integrate the Algolia Search API to your Django project. It's based on the algoliasearch-client-python package.
You might be interested in this sample Django application providing a typeahead.js based auto-completion and Google-like instant search: algoliasearch-django-example.
- Compatible with Python 2.7 and Python 3.4+.
- Supports Django 1.7+, 2.x and 3.x.
pip install algoliasearch-django
In your Django settings, add algoliasearch_django
to INSTALLED_APPS
and add these two settings:
ALGOLIA = {
'APPLICATION_ID': 'MyAppID',
'API_KEY': 'MyApiKey'
}
There are several optional settings:
INDEX_PREFIX
: prefix all indices. Use it to separate different applications, likesite1_Products
andsite2_Products
.INDEX_SUFFIX
: suffix all indices. Use it to differentiate development and production environments, likeLocation_dev
andLocation_prod
.AUTO_INDEXING
: automatically synchronize the models with Algolia (default to True).RAISE_EXCEPTIONS
: raise exceptions on network errors instead of logging them (default to settings.DEBUG).
Create an index.py
inside each application that contains the models you want to index.
Inside this file, call algoliasearch.register()
for each of the models you want to index:
# index.py
import algoliasearch_django as algoliasearch
from .models import YourModel
algoliasearch.register(YourModel)
By default, all the fields of your model will be used. You can configure the index by creating a subclass of AlgoliaIndex
and using the register
decorator:
# index.py
from algoliasearch_django import AlgoliaIndex
from algoliasearch_django.decorators import register
from .models import YourModel
@register(YourModel)
class YourModelIndex(AlgoliaIndex):
fields = ('name', 'date')
geo_field = 'location'
settings = {'searchableAttributes': ['name']}
index_name = 'my_index'
python manage.py algolia_reindex
: reindex all the registered models. This command will first send all the record to a temporary index and then moves it.- you can pass
--model
parameter to reindex a given model
- you can pass
python manage.py algolia_applysettings
: (re)apply the index settings.python manage.py algolia_clearindex
: clear the index
We recommend using our InstantSearch.js library to build your search interface and perform search queries directly from the end-user browser without going through your server.
However, if you want to search from your backend you can use the raw_search(YourModel, 'yourQuery', params)
method.
It retrieves the raw JSON answer from the API, and accepts in param
any
search parameters.
from algoliasearch_django import raw_search
params = { "hitsPerPage": 5 }
response = raw_search(Contact, "jim", params)
Use the geo_field
attribute to localize your record. geo_field
should be a callable that returns a tuple (latitude, longitude).
class Contact(models.model):
name = models.CharField(max_length=20)
lat = models.FloatField()
lng = models.FloatField()
def location(self):
return (self.lat, self.lng)
class ContactIndex(AlgoliaIndex):
fields = 'name'
geo_field = 'location'
algoliasearch.register(Contact, ContactIndex)
Use the tags
attributes to add tags to your record. It can be a field or a callable.
class ArticleIndex(AlgoliaIndex):
tags = 'category'
At query time, specify { tagFilters: 'tagvalue' }
or { tagFilters: ['tagvalue1', 'tagvalue2'] }
as search parameters to restrict the result set to specific tags.
You can choose which field will be used as the objectID
. The field should be unique and can
be a string or integer. By default, we use the pk
field of the model.
class ArticleIndex(AlgoliaIndex):
custom_objectID = 'post_id'
You can customize the index name. By default, the index name will be the name of the model class.
class ContactIndex(algoliaindex):
index_name = 'Enterprise'
If you want to process a field before indexing it (e.g. capitalizing a Contact
's name
),
or if you want to index a related object's
attribute, you need to define proxy methods for these fields.
class Account(models.Model):
username = models.CharField(max_length=40)
service = models.CharField(max_length=40)
class Contact(models.Model):
name = models.CharField(max_length=40)
email = models.EmailField(max_length=60)
//...
accounts = models.ManyToManyField(Account)
def account_names(self):
return [str(account) for account in self.accounts.all()]
def account_ids(self):
return [account.id for account in self.accounts.all()]
from algoliasearch_django import AlgoliaIndex
class ContactIndex(AlgoliaIndex):
fields = ('name', 'email', 'company', 'address', 'city', 'county',
'state', 'zip_code', 'phone', 'fax', 'web', 'followers', 'account_names', 'account_ids')
settings = {
'searchableAttributes': ['name', 'email', 'company', 'city', 'county', 'account_names',
}
- With this configuration, you can search for a
Contact
using itsAccount
names - You can use the associated
account_ids
at search-time to fetch more data from your model (you should only proxy the fields relevant for search to keep your records' size as small as possible)
We provide many ways to configure your index allowing you to tune your overall index relevancy. All the configuration is explained on our doc.
class ArticleIndex(AlgoliaIndex):
settings = {
'searchableAttributes': ['name', 'description', 'url'],
'customRanking': ['desc(vote_count)', 'asc(name)']
}
You can add constraints controlling if a record must be indexed or not. should_index
should be a
callable that returns a boolean.
class Contact(models.model):
name = models.CharField(max_length=20)
age = models.IntegerField()
def is_adult(self):
return (self.age >= 18)
class ContactIndex(AlgoliaIndex):
should_index = 'is_adult'
It is possible to have several indices for a single model.
- First, define all your indices that you want for a model:
from algoliasearch_django import AlgoliaIndex
class MyModelIndex1(AlgoliaIndex):
name = 'MyModelIndex1'
...
class MyModelIndex2(AlgoliaIndex):
name = 'MyModelIndex2'
...
- Then, define a meta model which will aggregate those indices:
class MyModelMetaIndex(AlgoliaIndex):
def __init__(self, model, client, settings):
self.indices = [
MyModelIndex1(model, client, settings),
MyModelIndex2(model, client, settings),
]
def raw_search(self, query='', params=None):
res = {}
for index in self.indices:
res[index.name] = index.raw_search(query, params)
return res
def update_records(self, qs, batch_size=1000, **kwargs):
for index in self.indices:
index.update_records(qs, batch_size, **kwargs)
def reindex_all(self, batch_size=1000):
for index in self.indices:
index.reindex_all(batch_size)
def set_settings(self):
for index in self.indices:
index.set_settings()
def clear_index(self):
for index in self.indices:
index.clear_index()
def save_record(self, instance, update_fields=None, **kwargs):
for index in self.indices:
index.save_record(instance, update_fields, **kwargs)
def delete_record(self, instance):
for index in self.indices:
index.delete_record(instance)
- Finally, register this
AlgoliaIndex
with yourModel
:
import algoliasearch_django as algoliasearch
algoliasearch.register(MyModel, MyModelMetaIndex)
It is possible to temporarily disable the auto-indexing feature using the disable_auto_indexing
context decorator:
from algoliasearch_django.decorators import disable_auto_indexing
# Used as a context manager
with disable_auto_indexing():
MyModel.save()
# Used as a decorator
@disable_auto_indexing():
my_method()
# You can also specifiy for which model you want to disable the auto-indexing
with disable_auto_indexing(MyModel):
MyModel.save()
MyOtherModel.save()
To run the tests, first find your Algolia application id and Admin API key (found on the Credentials page).
ALGOLIA_APPLICATION_ID={APPLICATION_ID} ALGOLIA_API_KEY={ADMIN_API_KEY} tox
To override settings for some tests, use the settings method:
class OverrideSettingsTestCase(TestCase):
def setUp(self):
with self.settings(ALGOLIA={
'APPLICATION_ID': 'foo',
'API_KEY': 'bar',
'AUTO_INDEXING': False
}):
algolia_engine.reset(settings.ALGOLIA)
def tearDown(self):
algolia_engine.reset(settings.ALGOLIA)
def test_foo():
# ...
If you want to contribute to this project without installing all its dependencies, you can use our Docker image. Please check our dedicated guide to learn more.
Encountering an issue? Before reaching out to support, we recommend heading to our FAQ where you will find answers for the most common issues and gotchas with the package.