Используя Django, как я могу получить набор записей, где значение, используемое для фильтрации, относится к полю "многие ко многим" - PullRequest
0 голосов
/ 28 марта 2020

Если у меня есть данные, которые похожи на:

id | value | m2m__created | m2m__value
---+-------+--------------+-----------
 1 | 10    | 2020-03-14   | 0
 1 | 10    | 2020-03-21   | 5
 2 | 20    | 2020-03-14   | 10
 3 | 30    | 2020-03-14   | 20

, что я хочу после фильтрации:

id | value | m2m__created | m2m__value
---+-------+--------------+-----------
 1 | 10    | 2020-03-21   | 5
 2 | 20    | 2020-03-14   | 10
 3 | 30    | 2020-03-14   | 20

Я пытаюсь использовать что-то вроде этого:

Foo.objects.filter(
    foo_m2m__created__lte=start_date,
).order_by(
    'id',
    '-foo_m2m__created',
).annotate(
    recently_created=Max('foo_m2m__created'),
).values(
    'id',
    'value',
    'foo_m2m__created',
    'foo_m2m__value',
)

К сожалению, я получаю следующее:

id | value | m2m__created | m2m__value
---+-------+--------------+-----------
 1 | 10    | 2020-03-14   | 0
 2 | 20    | 2020-03-14   | 10
 3 | 30    | 2020-03-14   | 20

Я попытался добавить еще один .filter(foo_m2m__created=F('recently_created')) после аннотации, но происходит то же самое.

1 Ответ

0 голосов
/ 30 марта 2020

Я смог сделать это, используя что-то вроде:

foo_max_set = Foo.objects.filter(
    foo_m2m__created__lte=start_date,
).values(
    'id',
    'foo_m2m__created',
).annotate(
    max_created=Max('foo_m2m__created')
).order_by('id')

q_statement = Q()
for item in foo_max_set:
    q_statement |= (Q(pk=item['id']) & Q(foo_m2m__created=item['max_created']))

foo_history = Foo.objects.filter(q_statement).distinct().values(
    'id',
    'value',
    'foo_m2m__value'
)

Это дает то, что мне нужно, с помощью двух запросов, и это лучшее, чего мне удалось добиться. Мне все еще было бы интересно увидеть что-то, что делает это в одном, если бы был умный путь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...