Django оставил внешнее соединение с фильтром

Я использую встроенную пользовательскую модель Django и имею пользовательский объект Foo с ForeignKey для пользователя. Я хочу выбрать все объекты User и все объекты Foo, которые соответствуют определенным ограничениям, например:

SELECT * from auth_user LEFT OUTER JOIN "foo" ON (auth_user.id = foo.id AND <other criteria here>) 

Как это сделать в Django? До сих пор я пробовал:

 User.objects.filter(foo__<criteria>) 

но это генерирует SQL, подобный этому:

 SELECT * from auth_user LEFT OUTER JOIN "foo" ON (auth_user.id = foo.id) WHERE <other criteria here> 

и возвращает только объекты User, у которых есть объекты Foo, которые соответствуют критериям. В качестве альтернативы я могу выбрать все объекты пользователя и выполнить запрос для каждого из них, но это будет значительно менее эффективно.

Если вы хотите, чтобы Django извлекал все объекты User и все объекты Foo , связанные с пользовательским объектом, вы должны использовать select_related() :

 User.objects.all().select_related('foo') 

но здесь вы не хотите, чтобы все объекты Foo были связаны с пользовательским объектом, вы просто хотите, чтобы подмножество из них удовлетворяло вашим критериям. Я не знаю, как рассказать Django об этом в одном наборе запросов. Но то, что вы можете сделать, – это сделать оба выбора отдельно и выполнить соединение в Python:

 # Map from user id to corresponding Foo satisfying <criteria>, if any. foos = {foo.user_id: foo for foo in Foo.objects.filter(user__isnull = False, <criteria>)} for user in User.objects.all(): foo = foos.get(user.id) # ... 

(Это больше не делает работу с базой данных или не переносит больше данных, чем ваш LEFT OUTER JOIN , поэтому я считаю, что это разумный подход.)

Это неудобно, но это должно сделать это:

 User.objects.raw('SELECT auth_user.* from auth_user LEFT OUTER JOIN ' '"foo" ON (auth_user.id = foo.id AND ' '<other criteria here>)') 

Вы можете использовать дополнительные атрибуты для возвращаемых объектов пользователя, добавив их в левую часть выбора.