Аннотация запросов Django не поддерживает вычисление math.tan()

У меня есть сайт django 3.2/mysql. Одна из таблиц, Flights, имеет два столбца, angle и baseline. Эти два столбца объединены в представлении для отображения значения altitude с помощью формулы altitude = baseline * tan(angle). Я создаю форму поиска для этой таблицы, и пользователь хочет искать рейсы, используя minimum altitude и maximum altitude.

Мой обычный подход к проблеме состоит в том, чтобы собрать входные данные из формы поиска, создать соответствующие Q-операторы и использовать запрос к таблице с фильтрами, основанными на Q-операторах. Однако, поскольку нет поля altitude, я должен аннотировать запрос полем altitude value, чтобы оператор Q с высотой работал.

Похоже, что в аннотации запроса нельзя использовать выражение типа math.tan(field_name). Например,

Flights.objects.annotate(altitude_m=ExpressionWrapper(expression=(F('baseline') * math.tan(F("angle"))), output_field = models.FloatField(),),)

генерирует ошибку builtins.TypeError: must be real number, not F

где выражение

Flights.objects.annotate(altitude_m=ExpressionWrapper(expression=(F('baseline') * F("angle")), output_field = models.FloatField(),),)

не генерирует ошибку, но и не дает правильного значения.

Есть ли способ аннотировать запрос к таблице Flights со значением altitude, чтобы я мог добавить фильтр типа Q(altitude__gte= min_altitude) к запросу? Или лучше всего (1) вернуться к существующим ~1000 строкам в таблице Flights и добавить столбец altitude и вставить вычисленное значение, или (2) отфильтровать запрос Flights по другим критериям поиска и в python вычислить высоту для каждого объекта Flights в отфильтрованном наборе запросов и отбросить те, которые не соответствуют критериям поиска высоты?

Примечание: Я несколько упростил описание проблемы, описав только одно значение высоты. На самом деле существует 2 значения высоты, одно в метрах, другое в футах.

Спасибо!

Используйте функцию базы данных Tan

from django.db.models.functions import Tan

Flights.objects.annotate(
    altitude=ExpressionWrapper(expression=F('baseline') * Tan('angle'), output_field=models.FloatField())
)
Вернуться на верх