Django orm subquery - в предложении без подстановки

Мне нужно построить запрос, используя Django ORM, который выглядит как этот запрос на SQL:

select * from A where id not in (select a_id from B where ... )

Я пытаюсь использовать такой код:

ids = B.objects.filter(...)
a_objects = A.object.exclude(id__in=Subquery(ids.values('a__id'))).all()

Проблема в том, что вместо вложенного select Django генерирует запрос, который выглядит как

select * from A where id not in (1, 2, 3, 4, 5 ....)

в пункте where in явно перечислены все идентификаторы, которые должны быть исключены, что делает результирующий sql нечитаемым при печати в журналы. Можно ли изменить этот запрос, чтобы использовался вложенный select?

Итак, я вижу, что ваша цель - получить все A, которые не имеют отношений внешних ключей с B. Если я прав, то вы можете просто использовать инверсный поиск для этого.

Итак, когда вы определяете модели таким образом:

class A:
    pass

class B:
    a = ForeignKey(to=a, related_name='bs')

Вы можете отфильтровать его следующим образом:

A.objects.filter(bs__isnull=True)

Кроме того, если вы не определите related_name, по умолчанию будет установлено b_set, так что вы сможете A.objects.filter(b_set__isnull=True)

чтобы сделать фильтр на B, вы можете

ids  = B.objects.filter(x=x).values_list('id',flat=true)

вы получаете список идентификаторов, затем делаете

a_objects = A.object.exclude(id__in=ids)

как уже говорилось ранее, если существует отношение

Вам не нужно делать ничего особенного, просто используйте queryset непосредственно в вашем фильтре.

ids = B.objects.filter(...)
a_objects = A.object.exclude(id__in=ids).all()

# that should generate the subquery statement
select * from A where NOT (id in (select a_id from B where ... ))
Вернуться на верх