按相对于给定位置的距离对查询集进行排序

时间:2015-07-29 15:02:58

标签: python mysql django orm geospatial

我有一个包含纬度和经度信息的模型,如FloatFields。

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

我想通过距给定位置(lat,lon)越来越远的距离来命令这个模型,但似乎不能使用F()表达式(使用hasrsine库,我没有成功)将它们转换为浮点数)

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

此查询将引发以下TypeError:

float() argument must be a string or a number

我也尝试使用带有FloatField()的ExpressionWrapper作为output_field参数,但没有成功。

我怎么能实现这个目标?

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

Func是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')

基于this post

答案 1 :(得分:0)

请注意https://docs.djangoproject.com/en/1.8/ref/models/expressions/#f-expressions"生成SQL"和float("生成sql")没有意义。 "生成sql" ==使用生成的sql中的字段值。您必须使用知道如何将自身转换为执行繁重计算的sql且与django成为朋友的东西来更改hasrsine函数...

你肯定要有创意来优雅地解决这个问题。如果你可以编写sql进行计算,原始sql似乎是获得结果的最快方法。考虑使用像postgis这样的地理扩展。如果你有一组小而固定的输入(lat,lon)组合或"预计算估计"你可以考虑预先计算。能够限制查询结果计数并在python中计算和排序。