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

Python 按相对于给定位置的距离排序查询集,python,mysql,django,orm,geospatial,Python,Mysql,Django,Orm,Geospatial,我有一个包含纬度和经度信息的模型,作为浮动字段 class Trader(models.Model): latitude = models.FloatField() longitude = models.FloatField() 我想按离给定位置(lat,lon)越来越远的距离来订购此模型,但似乎无法使用F()表达式(使用haversine库,我尚未成功地将它们转换为浮点数) 此查询引发以下TypeError: float() argument must be a string

我有一个包含纬度和经度信息的模型,作为浮动字段

class Trader(models.Model):
    latitude = models.FloatField()
    longitude = models.FloatField()
我想按离给定位置(lat,lon)越来越远的距离来订购此模型,但似乎无法使用F()表达式(使用haversine库,我尚未成功地将它们转换为浮点数)

此查询引发以下TypeError:

float() argument must be a string or a number
我还尝试使用ExpressionWrapper和FloatField()作为输出字段参数,但没有成功

我怎样才能做到这一点

提前感谢您的帮助

请注意,“生成SQL”和float(“生成SQL”)没有意义。“生成sql”==使用生成的sql中字段的值。你必须改变haversine函数,让它知道如何将自己转换成sql,它可以进行大量的计算,并且是django的朋友

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

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

基于。

函数
F()
返回什么(数据类型)?我怀疑它正在返回某种序列(列表、元组等)。这是否回答了您的问题?经过大量的搜索,你的答案是最有帮助的。我将这段代码包装在一个对象管理器类中。可在以下要点中找到:
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')