Имеется 2 таблицы:
class Sale(models.Model):
percent = models.FloatField()
class Product(models.Model):
sale = models.ForeignKey(Sale, null=True, blank=True)
price = models.FloatField()
Необходимо отфильтровать товары по диапазону цены. При этом на цену может влиять скидка, т.е. если фильтруем по цене от $10 до $80, то товар ценой в $120 с 50% скидкой должен попасть в выборку, тк со скидкой он будет стоить $60.
products = Product.objects.filter(price__range=(10, 80))
не подходит, т.к. не учитывает скидку.
products = Product.objects.annotate(price_with_sale=F('price')*(1-F('sale__percent')))
products = products.filter(price_with_sale__range=(10, 80))
не подходит т.к. не у всех товаров есть скидка.
Вариант создать по умолчанию для товаров нулевую скидку не рассматривается.
Есть вариант разбить выборку на две: товары со скидкой и товары без скидки. Первую по одному отфильтровать, а вторую по другому. И в конце их объединить. Это два дополнительных запроса. Он мне не кажется оптимальным.
def filter_prices(self, products, price_from, price_to):
products1 = Product.objects.filter(sale__isnull=True)
products1 = products1.filter(price__range=(price_from, price_to))
products2 = Product.objects.filter(sale__isnull=False)
products2 = products2.annotate(new_price=F('price')*(1-F('sale__percent')))
products2 = products2.filter(new_price__range=(price_from, price_to))
ids = list(chain(products1.values_list('id', flat=True), products2.values_list('id', flat=True)))
return products.filter(id__in=ids)
Откровенно говоря я даже не представляю как такое можно сделать sql запросом, следовательно и orm тут ничего не сделает.
Я хочу невозможного или упускаю какой то элементарный способ из виду?