Tips’n Tricks

Reusing Model serializers

It may be useful to be able to use existing model serializers to return data from search requests in the same format as used elsewhere in your API. This can be done by modifying the to_representation method of your serializer to use the instance.object instead of the search result instance. As a convenience, a mixin class is provided that does just that.

class drf_haystack.serializers.HaystackSerializerMixin

An example using the mixin might look like the following:

class PersonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Person
        fields = ("id", "firstname", "lastname")

class PersonSearchSerializer(HaystackSerializerMixin, PersonSerializer):
    class Meta(PersonSerializer.Meta):
        search_fields = ("text", )

The results from a search would then contain the fields from the PersonSerializer rather than fields from the search index.

Note

If your model serializer specifies a fields attribute in its Meta class, then the search serializer must specify a search_fields attribute in its Meta class if you intend to search on any search index fields that are not in the model serializer fields (e.g. ‘text’)

Warning

It should be noted that doing this will retrieve the underlying object which means a database hit. Thus, it will not be as performant as only retrieving data from the search index. If performance is a concern, it would be better to recreate the desired data structure and store it in the search index.

Regular Search View

Sometimes you might not need all the bells and whistles of a ViewSet, but can do with a regular view. In such scenario you could do something like this.

#
# views.py
#

from rest_framework.mixins import ListModelMixin
from drf_haystack.generics import HaystackGenericAPIView


class SearchView(ListModelMixin, HaystackGenericAPIView):

    serializer_class = LocationSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)


#
# urls.py
#

urlpatterns = (
   ...
    url(r'^search/', SearchView.as_view()),
   ...
)

You can also use FacetMixin or MoreLikeThisMixin in your regular views as well.

#
# views.py
#

from rest_framework.mixins import ListModelMixin
from drf_haystack.mixins import FacetMixin
from drf_haystack.generics import HaystackGenericAPIView


class SearchView(ListModelMixin, FacetMixin, HaystackGenericAPIView):
    index_models = [Project]
    serializer_class = ProjectListSerializer
    facet_serializer_class = ProjectListFacetSerializer

    pagination_class = BasicPagination
    permission_classes = (AllowAny,)

    def get(self, request, *args, **kwargs):
        return self.facets(request, *args, **kwargs)