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

6

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

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

我希望能够按照给定位置(纬度,经度)与该模型之间的距离逐渐增加的顺序订购该模型,但是使用F()表达式似乎无法做到这一点(使用haversine库时,我没有成功将它们转换为浮点数)

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

这个查询会抛出以下类型错误:
float() argument must be a string or a number

我也尝试使用 ExpressionWrapper 和 FloatField() 作为输出字段参数,但没有成功。

我该如何实现呢?

非常感谢您的任何帮助!


你的函数 F() 返回什么类型的数据?我怀疑它返回某种序列(列表、元组等)。 - Alan Hoover
这个回答对你有帮助吗?Django按距离排序 - Francisco
2个回答

4

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

基于这篇文章


经过大量搜索,您的答案是最有帮助的。敬启者,我将此代码封装在一个对象管理器类中。它可以在此Gist中找到:https://gist.github.com/rchrd2/5e0b014640a459a14ef038975d2a3683 - rchrd2

0
请注意,https://docs.djangoproject.com/en/1.8/ref/models/expressions/#f-expressions "生成 SQL",而 float("generate sql") 没有意义。"generate sql" == 在生成的 SQL 中使用字段的值。您需要使用某些知道如何将自己翻译成执行大量计算并与 Django 友好的 SQL 的内容来更改 haversine 函数...
您肯定需要有创意才能优雅地解决这个问题。如果您可以编写 SQL 来执行该计算,则原始 SQL 似乎是最快的方法来获得结果。考虑使用像 postgis 这样的地理扩展。如果您具有小型且固定的输入(lat、lon)组合集,则可以考虑预计算或“预计算估计”,以便能够限制查询结果计数并在 Python 中进行计算和排序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接