Как сделать запрос фильтра со значениями набора запросов, используя объекты Q и оператор &? - PullRequest
1 голос
/ 02 июня 2019

Не могли бы вы поддержать меня следующим вопросом?

У меня есть эти модели:

class Tarifa(models.Model):
    limite_i = models.DecimalField(max_digits=10, decimal_places=2)
    limite_s = models.DecimalField(max_digits=10, decimal_places=2)


class Calculator(models.Model):
    tarifa = models.ForeignKey(Tarifa, on_delete=models.CASCADE)
    base = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    limite = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)

У меня есть первый набор запросов, который приносит информацию о строке моей модели калькулятора:

qsl1 = Calculator.objects.values_list('base')

Этот набор запросов возвращает все суммы, которые у меня есть в базе:

<QuerySet [(Decimal('3000.00'),), (Decimal('5000.00'),), (Decimal('1000.00'),)]>

Позже я ввожу этот запрос как подзапрос в следующем наборе запросов:

qsl2 = Tarifa.objects.filter(
Q(limite_s__gte=qsl1) 
& Q(limite_i_isr__lte=qsl1))
.values_list('limite_i')

Это второй запрос значений, которые мои «limit_s»> = «base» и «limit_i» <= «base», а затем приносят мне значение «limit_i» </p>

Теперь проблема в том, что я тольковернуть сравнение первого значения, которое составляет 3000,00, мне также нужно сделать сравнение 5000,00 и 1000,00 и всех других добавляемых значений.

Но я не знаю, как вы могли бы поддержать меня,Большое спасибо.

Ответы [ 2 ]

1 голос
/ 02 июня 2019

Я бы предложил вызывать values_list с атрибутом flat, когда вам нужно только одно поле.

bases = Calculator.objects.values_list('base', flat=True)

Это вернет свернутую версию набора запросов:

<QuerySet [Decimal('3000.00'), Decimal('5000.00'), Decimal('1000.00')]>

После выборкиоснований, с которыми вы должны сделать объект Q или запросы, как показано ниже:

import operator
from itertools import reduce

query_args = []
for base in bases:
    query_args.append(
        Q(limite_s__gte=base) & Q(limite_i__lte=base)
    )

query = reduce(operator.or_, query_args)

tarifas = Tarifa.objects.filter(query).values_list('limite_i', flat=True)
0 голосов
/ 02 июня 2019

Если вы обновите свое поле ForeignKey с помощью related_name следующим образом:

class Calculator(models.Model):
    tarifa = models.ForeignKey(Tarifa, on_delete=models.CASCADE, related_name='calculators')
    base = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    limite = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)

Тогда вы можете попробовать вот так:

Tarifa.objects.filter(Q(limite_s__gte=F('calculators__base'))&Q(limite_i__lte=F('calculators__base')))
...