I m trying to make autocomplete api for one model in django. First time using haystack with elastic search. When i hit api SearchQuerySet return array of empty objects.
models.py
from __future__ import unicode_literals
from django.db import models
class Movie(models.Model):
title = models.CharField(max_length=250)
year = models.CharField(max_length=250)
location = models.CharField(max_length=250)
fun_fact = models.CharField(max_length=250, null=True)
production_company = models.CharField(max_length=250)
director = models.CharField(max_length=250)
actor1 = models.CharField(max_length=250)
actor2 = models.CharField(max_length=250, null=True)
actor3 = models.CharField(max_length=250, null=True)
longitude = models.DecimalField(max_digits=9, decimal_places=6)
latitude = models.DecimalField(max_digits=9, decimal_places=6)
def __str__(self):
return self.title
search_indexes.py
from haystack import indexes
from models import Movie
class MovieIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
year = indexes.CharField(model_attr='year')
content_auto = indexes.EdgeNgramField(model_attr='title')
def get_model(self):
return Movie
def index_queryset(self, using=None):
"""Used when the entire index for model is updated."""
return self.get_model().objects.all()
views.py
from django.shortcuts import render
# Create your views here.
import json
from django.http import HttpResponse
from haystack.query import SearchQuerySet
def autocomplete(request):
sqs = SearchQuerySet().all()
suggestions = [result.title for result in sqs]
# Make sure you return a JSON object, not a bare list.
# Otherwise, you could be vulnerable to an XSS attack.
the_data = json.dumps({
'results': suggestions
})
return HttpResponse(the_data, content_type='application/json')
movie_text.txt
{{ object.title }}
{{ object.year }}
{{ object.production_company }}
{{ object.director }}
Indexing is done below is my index data
{
"took": 60,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 22,
"max_score": 1,
"hits": [
{
"_index": "haystack",
"_type": "modelresult",
"_id": "app.movie.7",
"_score": 1,
"_source": {
"django_ct": "app.movie",
"django_id": "7",
"year": "1978",
"text": "A Night Full of Rain\n1978\nLiberty Film\nLina Wertmuller\n",
"id": "app.movie.7"
}
},
{
"_index": "haystack",
"_type": "modelresult",
"_id": "app.movie.9",
"_score": 1,
"_source": {
"django_ct": "app.movie",
"django_id": "9",
"year": "1997",
"text": "A Smile Like Yours\n1997\nParamount Pictures\nKeith Samples\n",
"id": "app.movie.9"
}
},
{
"_index": "haystack",
"_type": "modelresult",
"_id": "app.movie.13",
"_score": 1,
"_source": {
"django_ct": "app.movie",
"django_id": "13",
"year": "1985",
"text": "A View to a Kill\n1985\nMetro-Goldwyn Mayer\nJohn Glen\n",
"id": "app.movie.13"
}
},
{
"_index": "haystack",
"_type": "modelresult",
"_id": "app.movie.14",
"_score": 1,
"_source": {
"django_ct": "app.movie",
"django_id": "14",
"year": "1985",
"text": "A View to a Kill\n1985\nMetro-Goldwyn Mayer\nJohn Glen\n",
"id": "app.movie.14"
}
},
{
"_index": "haystack",
"_type": "modelresult",
"_id": "app.movie.16",
"_score": 1,
"_source": {
"django_ct": "app.movie",
"django_id": "16",
"year": "1985",
"text": "A View to a Kill\n1985\nMetro-Goldwyn Mayer\nJohn Glen\n",
"id": "app.movie.16"
}
},
{
"_index": "haystack",
"_type": "modelresult",
"_id": "app.movie.20",
"_score": 1,
"_source": {
"django_ct": "app.movie",
"django_id": "20",
"year": "1936",
"text": "After the Thin Man\n1936\nMetro-Goldwyn Mayer\nW.S. Van Dyke\n",
"id": "app.movie.20"
}
},
{
"_index": "haystack",
"_type": "modelresult",
"_id": "app.movie.22",
"_score": 1,
"_source": {
"django_ct": "app.movie",
"django_id": "22",
"year": "2015",
"text": "Age of Adaline\n2015\nLionsgate / Sidney Kimmel Entertainment / Lakeshore Entertainment\nLee Toland Krieger\n",
"id": "app.movie.22"
}
},
{
"_index": "haystack",
"_type": "modelresult",
"_id": "app.movie.15",
"_score": 1,
"_source": {
"django_ct": "app.movie",
"django_id": "15",
"year": "1985",
"text": "A View to a Kill\n1985\nMetro-Goldwyn Mayer\nJohn Glen\n",
"id": "app.movie.15"
}
},
{
"_index": "haystack",
"_type": "modelresult",
"_id": "app.movie.17",
"_score": 1,
"_source": {
"django_ct": "app.movie",
"django_id": "17",
"year": "1985",
"text": "A View to a Kill\n1985\nMetro-Goldwyn Mayer\nJohn Glen\n",
"id": "app.movie.17"
}
},
{
"_index": "haystack",
"_type": "modelresult",
"_id": "app.movie.1",
"_score": 1,
"_source": {
"django_ct": "app.movie",
"django_id": "1",
"year": "2011",
"text": "180\n2011\nSPI Cinemas\nJayendra\n",
"id": "app.movie.1"
}
}
]
}
}
output of API
{
"results": [
null,
null,
null,
null,
null]
}
Don't see an issue with your indexes long as you ensure that indexes are updated. In your views you neither passing search query or using autocomplete field to query on. Please try with this.
def autocomplete(request):
search_query = request.GET.get("q",None)
if not search_query:
raise Http404
autosuggest = SearchQuerySet().autocomplete(content_auto=search_query)[:5]
try:
autosuggest_results = map(lambda x: x.object.title, autosuggest)
response = {"results": autosuggest_results}
return JsonResponse(response)
except Exception:
raise Http404()