File: 03_geospatial.rst

package info (click to toggle)
drf-haystack 1.8.4-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 584 kB
  • sloc: python: 2,594; makefile: 147
file content (87 lines) | stat: -rw-r--r-- 2,939 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
.. _geospatial-label:

GEO spatial locations
=====================

Some search backends support geo spatial searching. In order to take advantage of this we
have the :class:`drf_haystack.filters.HaystackGEOSpatialFilter`.

.. note::

    The ``HaystackGEOSpatialFilter`` depends on ``geopy`` and ``libgeos``. Make sure to install these
    libraries in order to use this filter.

    .. code-block:: none

        $ pip install geopy
        $ apt-get install libgeos-c1 (for debian based linux distros)
          or
        $ brew install geos (for homebrew on OS X)


The geospatial filter is somewhat special, and for the time being, relies on a few assumptions.

#. The index model **must** to have a ``LocationField`` (See :ref:`search-index-example-label` for example).
   If your ``LocationField`` is named something other than ``coordinates``, subclass the ``HaystackGEOSpatialFilter``
   and make sure to set the :attr:`drf_haystack.filters.HaystackGEOSpatialFilter.point_field` to the name of the field.
#. The query **must** contain a ``unit`` parameter where the unit is a valid ``UNIT`` in the ``django.contrib.gis.measure.Distance`` class.
#. The query **must** contain a ``from`` parameter which is a comma separated longitude and latitude value.

You may also change the query param ``from`` by defining ``DRF_HAYSTACK_SPATIAL_QUERY_PARAM`` on your settings.

**Example Geospatial view**

.. code-block:: python

    class DistanceSerializer(serializers.Serializer):
        m = serializers.FloatField()
        km = serializers.FloatField()


    class LocationSerializer(HaystackSerializer):

        distance = SerializerMethodField()

        class Meta:
            index_classes = [LocationIndex]
            fields = ["address", "city", "zip_code"]

        def get_distance(self, obj):
            if hasattr(obj, "distance"):
                return DistanceSerializer(obj.distance, many=False).data


    class LocationGeoSearchViewSet(HaystackViewSet):

        index_models = [Location]
        serializer_class = LocationSerializer
        filter_backends = [HaystackGEOSpatialFilter]


**Example subclassing the HaystackGEOSpatialFilter**

Assuming that your ``LocationField`` is named ``location``.

.. code-block:: python

    from drf_haystack.filters import HaystackGEOSpatialFilter

    class CustomHaystackGEOSpatialFilter(HaystackGEOSpatialFilter):
        point_field = 'location'


    class LocationGeoSearchViewSet(HaystackViewSet):

        index_models = [Location]
        serializer_class = LocationSerializer
        filter_backends = [CustomHaystackGEOSpatialFilter]

Assuming the above code works as it should, we would be able to do queries like this:

.. code-block:: none

    /api/v1/search/?zip_code=0351&km=10&from=59.744076,10.152045


The above query would return all entries with zip_code 0351 within 10 kilometers
from the location with latitude 59.744076 and longitude 10.152045.