1

I am using GeoDjango GIS for proximity search result based on latitude and longitude.

The model, is quiet simple:

class Address(gismodels.Model):
    # partner = models.ForeignKey(Partner, related_name="partner_addresses", on_delete=models.CASCADE)
    street = gismodels.CharField(max_length=255)
    city = gismodels.CharField(max_length=255)
    postcode = gismodels.CharField(max_length=255, null=True, blank=True, default='0000')
    country = gismodels.CharField(max_length=255)
    businesses = gismodels.OneToOneField(Business, related_name="business_address", on_delete=models.CASCADE, null=True)
    latitude = gismodels.FloatField(null=True, blank=True)
    longitude = gismodels.FloatField(null=True, blank=True)
    location = gismodels.PointField(null=True, blank=True)

    objects = gismodels.GeoManager()

    def __unicode__(self):
        return self.street

    class Meta:
        verbose_name = "Address"
        verbose_name_plural = "Addresses"

    def save(self, *args, **kwargs):
        if self.latitude and self.longitude:
            self.location = Point(self.longitude, self.latitude)

        super(Address, self).save(*args, **kwargs)

And, so is the serializer:

class AddressSerializer(HyperlinkedModelSerializer):
    name_of_business = serializers.CharField(source="businesses.name_of_business")
    business_id = serializers.IntegerField(source="businesses.pk")
    opening_time = serializers.TimeField(source="businesses.business_details.opening_time")

    class Meta:
        model = Address
        fields = ('pk', 'distance', 'street', 'city', 'postcode',
                  'name_of_business', "business_id",
                  'opening_time')

So, when I try to get response, say using curl http://127.0.0.1:5000/api/businesses/37.4418834/-122.14301949999998/, I get this error related to the distance field:

Traceback (most recent call last):
  File "/Users/dff/.virtualenvs/dff/lib/python2.7/site-packages/django/contrib/staticfiles/handlers.py", line 63, in __call__
    return self.application(environ, start_response)
  File "/Users/dff/.virtualenvs/dff/lib/python2.7/site-packages/whitenoise/base.py", line 66, in __call__
    return self.application(environ, start_response)
  File "/Users/dff/.virtualenvs/dff/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 189, in __call__
    response = self.get_response(request)
  File "/Users/dff/.virtualenvs/dff/lib/python2.7/site-packages/django/core/handlers/base.py", line 218, in get_response
    response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
  File "/Users/dff/.virtualenvs/dff/lib/python2.7/site-packages/django/core/handlers/base.py", line 261, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/Users/dff/.virtualenvs/dff/lib/python2.7/site-packages/django_extensions/management/technical_response.py", line 6, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/Users/dff/.virtualenvs/dff/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/dff/.virtualenvs/dff/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/dff/.virtualenvs/dff/lib/python2.7/site-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/dff/.virtualenvs/dff/lib/python2.7/site-packages/rest_framework/views.py", line 477, in dispatch
    response = self.handle_exception(exc)
  File "/Users/dff/.virtualenvs/dff/lib/python2.7/site-packages/rest_framework/views.py", line 437, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/Users/dff/.virtualenvs/dff/lib/python2.7/site-packages/rest_framework/views.py", line 448, in raise_uncaught_exception
    raise exc
ImproperlyConfigured: Field name `distance` is not valid for model `Address`.

Here is my api view:

class ProximityFilter(ListAPIView):
    serializer_class = AddressSerializer

    def get_queryset(self):
        longitude = self.kwargs.get('longitude')
        latitude = self.kwargs.get('latitude')
        current_point = GEOSGeometry('POINT(%s %s)' % (longitude, latitude), srid=4326)
        queryset = Address.objects.filter(city="SomeCity",location__distance_lte=(current_point, D(mi=700000000))).distance(
            current_point).order_by('distance')
        return queryset

How could I solve this to get distance through REST response? Any clues please? anyone? :)

Thanks

I am using Django 1.8.

Maverick
  • 2,738
  • 24
  • 91
  • 157
  • Apart from the issue, have you looked at https://github.com/djangonauts/django-rest-framework-gis? Because you can use the builtin DistanceToPointFilter. – Ozgur Vatansever Mar 27 '17 at 10:19
  • @ozgur I saw that, but was not sure if I could use it or if there could be an easier solution to this without going for another lib. Thanks for suggestion anyhow. – Maverick Mar 27 '17 at 10:24
  • Try `SerializerMethodField`. Refer this answer: https://stackoverflow.com/a/53307290/10290534 – nightfury Aug 02 '20 at 19:09

1 Answers1

2

The issue here is that you are trying to sort the queryset based on a nonexistent field named distance. You should annotate them using Distance() function first:

from django.contrib.gis.db.models.functions import Distance
Address.objects.filter(...).annotate(distance=Distance("location", current_point).order_by("distance")
Ozgur Vatansever
  • 49,246
  • 17
  • 84
  • 119
  • `from django.contrib.gis.db.models.functions import Distance` is only available from Django 1.9 I am using Django 1.8 – Maverick Mar 27 '17 at 10:37
  • 1
    I would suggest you upgrade your Django version. If you have to use 1.8, with a little bit effort, I think you can adopt its code to your app. https://github.com/django/django/blob/master/django/contrib/gis/db/models/functions.py#L255 – Ozgur Vatansever Mar 27 '17 at 10:41
  • with this, annotated `distance` would show up in API response? without adding `distance` to serializer fields? – Kishor Pawar May 10 '20 at 09:16