У меня есть ситуация, когда у меня есть модель под названием trip
. Каждая поездка имеет departure_airport
и arrival_airport
, которые являются связанными полями и обе являются частью модели airport
. Каждый объект в модели аэропорта имеет местоположение, представленное полями latitude
и longitude
.
Мне нужно иметь возможность получать информацию из двух (потенциально) отдельных мест вылета и прилета, используя что-то вроде формулы Хаверсайна. Эта формула рассчитывает расстояние от каждого аэропорта вылета / прилета в базе данных до местоположения аэропортов, которые были взяты в качестве входных данных.
Сложная часть этого запроса состоит в том, что я аннотирую набор запросов на поездки с указанием местоположения аэропортов отправления и прибытия, поскольку есть два набора полей широты / долготы (по одному для каждого аэропорта) с одинаковым именем, и вы можете ' Я не могу использовать аннотированные поля в предложении 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
Есть идеи? Также открыты для других способов сделать это.