【问题标题】:Ordering queryset by distance relative to a given position按相对于给定位置的距离对查询集进行排序
【发布时间】:2015-10-20 15:46:46
【问题描述】:

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

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

我想通过与给定位置(纬度,经度)的距离增加来订购此模型,但似乎无法使用 F() 表达式(使用 hasrsine 库,我没有成功将它们转换为浮点数)

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

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

我怎样才能做到这一点?

提前感谢您的帮助!

【问题讨论】:

  • 您的函数F() 返回什么(数据类型)?我怀疑它正在返回某种序列(列表,元组,...)。
  • 这能回答你的问题吗? Django sort by distance

标签: python mysql django orm geospatial


【解决方案1】:

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

【讨论】:

【解决方案2】:

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

您肯定必须发挥创造力才能优雅地解决这个问题。如果您可以编写 sql 来进行计算,原始 sql 似乎是获得结果的最快方法。例如,考虑使用像 postgis 这样的地理扩展。如果您有一组固定的输入(纬度、经度)组合或“预计算估计”以限制查询结果计数并在 python 中计算和排序,则可以考虑预计算。

【讨论】:

    猜你喜欢
    • 2015-08-06
    • 2015-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多