简体   繁体   English

Django注释无法访问模型的floatfield

[英]Django annotate cannot access model's floatfield

I am trying annotate a queryset with the object's distance from a user's provided location. 我正在尝试使用对象距用户提供的位置的距离注释查询集。 Here is what I have so far: 这是我到目前为止的内容:

lat1 = request.POST['lat']
lon1 = request.POST['lon']

locations = Location.objects.annotate(distance_away = posDifference('lat', 'lon', lat1, lon1)).order_by('distance_away')[0]

Here is the posDifference function, it returns the distance between the two points in miles. 这是posDifference函数,它返回两点之间的距离(以英里为单位)。

def posDifference(lat1, lon1, lat2, lon2):

    EARTH_RADIUS_IN_MILES = 3958.761

    lat1 = float(lat1)
    lon1 = float(lon1)
    lat2 = float(lat2)
    lon2 = float(lon2)

    lat1 = radians(lat1)
    lat2 = radians(lat2)

    delta_lon = radians(lon1 - lon2)
    cos_x = (sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(delta_lon)) # Distance formula
    distance = acos(cos_x) * EARTH_RADIUS_IN_MILES # Conversion to miles

    return distance

The error I am getting is ValueError: could not convert string to float: lat at line lat1 = float(lat1) in posDifference . 我得到的错误是ValueError: could not convert string to float: lat lat1 = float(lat1)posDifference I believe the strings 'lat' and 'lon' are being passed to the function instead of the Location object's fields lat and lon . 我相信字符串'lat''lon'将传递给函数,而不是Location对象的字段latlon

Of course they are just passed into function. 当然,它们只是传递给函数。 You're simply calling posDifference with that parameters. 您只是使用该参数调用posDifference I'm not sure why are you expecting other result... 我不确定您为什么期望其他结果...

You should build your function in different way, using F for referring to correct db column and Func for referring to some SQL functions ( sin , cos , acos ). 您应该以不同的方式构建函数,使用F引用正确的db列,并使用Func引用某些SQL函数( sincosacos )。 It can look like this: 它看起来可能像这样:

from django.db.models import Func, F

# It's better to build some library of used database functions first:
class Radians(Func):
    function = 'RADIANS'

class Sin(Func):
    function = 'SIN'

class Cos(Func):
    function = 'COS'

class Acos(Func):
    function = 'ACOS'

def posDifference(lat1, lon1, lat2, lon2):

    EARTH_RADIUS_IN_MILES = 3958.761

    lat1 = F(lat1)
    lon1 = F(lon1)
    lat2 = float(lat2)
    lon2 = float(lon2)

    lat1 = Radians(lat1)
    lat2 = radians(lat2)

    delta_lon = Radians(lon1) - radians(lon2)
    cos_x = (Sin(lat1) * sin(lat2) + Cos(lat1) * cos(lat2) * Cos(delta_lon)) # Distance formula
    distance = Acos(cos_x) * EARTH_RADIUS_IN_MILES # Conversion to miles

    return distance

That should work fine. 那应该工作正常。 More on that you can learn from django documentation 您可以从Django文档中学到更多

You sholud better use GeoDjango for that measurements. 您最好使用GeoDjango进行该测量。 There are ready for use functions for calculating distances, comparing distances, checking if point on map is inside some range or rectangle etc. All is done on database level and requires only some database extension. 提供了可供使用的功能,用于计算距离,比较距离,检查地图上的点是否在某个范围或矩形内等。所有这些操作均在数据库级别完成,并且仅需要某些数据库扩展即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM