Django:筛选带注释的值

时间:2019-03-26 22:58:25

标签: mysql django python-3.x

我遇到一个名为trip的模型的情况。每个行程都有一个departure_airportarrival_airport这两个相关字段,并且都是airport模型的一部分。机场模型中的每个对象都有一个由latitudelongitude字段表示的位置。

我需要能够使用Haversine公式从两个(可能)分开的出发和到达机场位置接收输入。该公式将计算从数据库中的每个出发/到达机场到已被用作输入的机场位置之间的距离。

此查询的困难之处在于,我用出发和到达机场的位置注释了旅行查询集,但是因为有两组纬度/经度字段(每个机场一组)具有相同的名称,所以您可以在sql where子句中使用带注释的字段,我无法在查询中同时使用两组机场。

我认为解决方案是在带注释的字段上使用子查询,以便查询在where子句之前执行,但是我无法确定此查询是否可行。另一种选择是编写raw_sql。

这是我到目前为止所拥有的:

GCD_FORMULA_TO = """3961 * acos(
    cos(radians(%s)) * cos(radians(arrival_lat))
    * cos(radians(arrival_lon) - radians(%s)) +
    sin(radians(%s)) * sin(radians(arrival_lat)))"""        

GCD_FORMULA_FROM = """3961 * acos(
    cos(radians(%s)) * cos(radians(departure_lat))
    * cos(radians(departure_lon) - radians(%s)) +
    sin(radians(%s)) * sin(radians(departure_lat)))"""

location_to = Q(location_to__lt=self.arrival_airport_rad)
location_from = Q(location_from__lt=self.departure_airport_rad)

qs = self.queryset\
    .annotate(arrival_lat=F('arrival_airport__latitude_deg'))\
   .annotate(arrival_lon_to=F('arrival_airport__longitude_deg'))\
    .annotate(departure_lat=F('departure_airport__latitude_deg'))\
    .annotate(longitude_lon=F('departure_airport__longitude_deg'))\
    .annotate(location_to=RawSQL(GCD_FORMULA_TO, (self.arrival_airport.latitude_deg, self.arrival_airport.longitude_deg, 
        self.arrival_airport.latitude_deg)))\
    .annotate(location_from=RawSQL(self.GCD_FORMULA_FROM, (self.departure_airport.latitude_deg, self.departure_airport.longitude_deg, 
        self.departure_airport.latitude_deg)))\
    .filter(location_to and location_from)

return qs

有什么想法吗?也可以采用其他方式解决此问题。

1 个答案:

答案 0 :(得分:1)

您很难做到这一点。

如果您的python代码具有一对位置,请使用this

from geopy.distance import distance

loc1 = (lat1, lng1)
loc2 = (lat2, lng2)
d = distance(loc1, loc2).km

如果要查询数据库,也许您希望它运行PostGIS / Postgres,而不是mysql, 因此您可以计算distance和形状成员。 语法有时在clunky side上,但是索引的作用很大。 这是一个从伦敦希思罗机场出发的例子:

SELECT    a.airport_name,
          ST_Distance('SRID=4326; POINT(-0.461389 51.4775)'::geography,
                      ST_Point(a.longitude, a.latitude)) AS distance
FROM      arrival_airports a
ORDER BY  distance;

作为另一件事,您可以考虑在表上定义到达和/或离开VIEW,然后再为每个视图使用不同的模型进行JOIN。