33"""
44
55from rest_framework .filters import BaseFilterBackend
6- from rest_framework .settings import api_settings
6+
7+
8+ from ..mixins import FilterBackendMixin
9+ from ...constants import (
10+ GEO_DISTANCE_ORDERING_PARAM ,
11+ )
712
813__title__ = 'django_elasticsearch_dsl_drf.filter_backends.ordering.common'
914__author__ = 'Artur Barseghyan <[email protected] >' 1217__all__ = ('GeoSpatialOrderingFilterBackend' ,)
1318
1419
15- class GeoSpatialOrderingFilterBackend (BaseFilterBackend ):
20+ class GeoSpatialOrderingFilterBackend (BaseFilterBackend , FilterBackendMixin ):
1621 """Geo-spatial ordering filter backend for Elasticsearch.
1722
1823 Example:
@@ -40,27 +45,46 @@ class GeoSpatialOrderingFilterBackend(BaseFilterBackend):
4045 >>> }
4146 """
4247
43- ordering_param = api_settings .ORDERING_PARAM
44-
45- # TODO: Either use or remove.
46- # @classmethod
47- # def prepare_ordering_fields(cls, view):
48- # """Prepare ordering fields.
49- #
50- # :param view: View.
51- # :type view: rest_framework.viewsets.ReadOnlyModelViewSet
52- # :return: Ordering options.
53- # :rtype: dict
54- # """
55- # ordering_fields = view.ordering_fields
56- # for field, options in ordering_fields.items():
57- # if options is None or isinstance(options, string_types):
58- # ordering_fields[field] = {
59- # 'field': options or field
60- # }
61- # elif 'field' not in ordering_fields[field]:
62- # ordering_fields[field]['field'] = field
63- # return ordering_fields
48+ ordering_param = GEO_DISTANCE_ORDERING_PARAM
49+
50+ @classmethod
51+ def get_geo_distance_params (cls , value , field ):
52+ """Get params for `geo_distance` ordering.
53+
54+ Example:
55+
56+ /api/articles/?geo_spatial_ordering=-location|45.3214|-34.3421|km|planes
57+
58+ :param value:
59+ :param field:
60+ :type value: str
61+ :type field:
62+ :return: Params to be used in `geo_distance` query.
63+ :rtype: dict
64+ """
65+ __values = cls .split_lookup_value (value , maxsplit = 3 )
66+ __len_values = len (__values )
67+
68+ if __len_values < 2 :
69+ return {}
70+
71+ params = {
72+ field : {
73+ 'lat' : __values [0 ],
74+ 'lon' : __values [1 ],
75+ }
76+ }
77+
78+ if __len_values > 2 :
79+ params ['unit' ] = __values [2 ]
80+ else :
81+ params ['unit' ] = 'm'
82+ if __len_values > 3 :
83+ params ['distance_type' ] = __values [3 ]
84+ else :
85+ params ['distance_type' ] = 'sloppy_arc'
86+
87+ return params
6488
6589 def get_ordering_query_params (self , request , view ):
6690 """Get ordering query params.
@@ -78,13 +102,16 @@ def get_ordering_query_params(self, request, view):
78102 __ordering_params = []
79103 # Remove invalid ordering query params
80104 for query_param in ordering_query_params :
81- __key = query_param .lstrip ('-' )
82- __direction = '-' if query_param .startswith ('-' ) else ''
105+ __key , __value = FilterBackendMixin .split_lookup_value (
106+ query_param .lstrip ('-' ),
107+ maxsplit = 1 ,
108+ )
109+ __direction = 'desc' if query_param .startswith ('-' ) else 'asc'
83110 if __key in view .geo_spatial_ordering_fields :
84111 __field_name = view .ordering_fields [__key ] or __key
85- __ordering_params . append (
86- '{}{}' . format ( __direction , __field_name )
87- )
112+ __params = self . get_geo_distance_params ( __value , __field_name )
113+ __params [ 'order' ] = __direction
114+ __ordering_params . append ( __params )
88115
89116 return __ordering_params
90117
0 commit comments