Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ordering queryset by distance relative to a given position

I have a model containing latitude and longitude information as FloatFields.

class Trader(models.Model):
    latitude = models.FloatField()
    longitude = models.FloatField()

I would like to order this model by an increasing distance from a given position(lat, lon) but can't seem to do so using F() expressions (using haversine library, I haven't succeeded in transforming them into float numbers)

Trader.objects.all().annotate(distance=haversine((lat, lon), (float(F('latitude')), float(F('longitude'))))).order_by('distance')

This query throws the following TypeError :

float() argument must be a string or a number

I have also tried using ExpressionWrapper with a FloatField() as output_field argument, without success.

How could I achieve that ?

Thank you in advance for any help !

like image 575
Ambroise Avatar asked Jul 29 '15 15:07

Ambroise


1 Answers

Func is new in Django 1.8.

from django.db.models import Func, F

class Sin(Func):
    function = 'SIN'

class Cos(Func):
    function = 'COS'

class Acos(Func):
    function = 'ACOS'

class Radians(Func):
    function = 'RADIANS'

radlat = Radians(latitude) # given latitude
radlong = Radians(longitude) # given longitude
radflat = Radians(F('latitude'))
radflong = Radians(F('longitude'))

Expression = 3959.0 * Acos(Cos(radlat) * Cos(radflat) *
                           Cos(radflong - radlong) +
                           Sin(radlat) * Sin(radflat))

Trader.objects.annotate(distance=Expression).order_by('distance')

Based on this post.

like image 73
f43d65 Avatar answered Nov 14 '22 22:11

f43d65