Django ForeignKey с null=True, внутренним объединением и оставленным внешним объединением

Скажем, у меня есть две модели Person и Company Django следующим образом: -

class Company(models.Model):
    name = models.CharField()

class Person(models.Model):
    last_name = models.CharField(blank=True)
    first_name = models.CharField()
    company = models.ForeignKey(Company, null=True, blank=True)

Человек может или не может принадлежать Компании.

Я использую MySQL. Я хочу всех Людей, которые не принадлежат никакой Компании, то есть, Люди, где компания является пустой.

Если я делаю Person.objects.filter(company__isnull=True) Я получаю SQL, который является по существу: -

SELECT * FROM PersonTable LEFT OUTER JOIN AgencyTable ON (PersonTable.company_id = AgencyTable.id) WHERE AgencyTable.id IS NULL

Как делают я иду о достижении следующего SQL: -

SELECT * FROM PersonTable INNER JOIN AgencyTable ON (PersonTable.company_id = AgencyTable.id) WHERE AgencyTable.id IS NULL

Из того, что я собираюсь из чтения списка рассылки Django Users, это раньше было поведением, прежде чем QuerySet Осуществят рефакторинг.

РЕДАКТИРОВАНИЕ - Теперь я вижу богохульство своего вопроса!

То, что я хочу сказать, я просто хочу сделать

SELECT * FROM PersonTable WHERE PersonTable.company_id IS NULL

9
задан chefsmart 17 February 2010 в 05:46
поделиться

2 ответа

Это должно быть так просто, как:

Person.objects.filter(company_id__isnull=True)

Обратите внимание на использование company_id , которое является целочисленным полем по умолчанию, созданным ForeignKey

Edit

Извините, я не использовал активно django начиная с 0.9.5. Либо я думаю о поведении до версии 1.0, либо я путаю sqlalchemy и Django ORM. В любом случае, как указано в комментариях, вышеуказанное не работает.

Похоже, что единственный способ получить нужный запрос в текущем django - это использовать параметр запроса .extra , который содержит целый список предостережений.

Person.objects.extra(where=['company_id IS NULL'])

Обратите внимание, что это может не быть переносимым для всех баз данных, и это может не работать в сочетании с filter () и любым количеством возможных проблем. Я бы рекомендовал не использовать это во всем вашем коде, а вместо этого перенести его в метод класса на Person, например:

 @classmethod
 def list_unaffiliated_people(cls):
    return cls.objects.extra(where=['company_id IS NULL'])

В качестве альтернативы, просто используйте правильный синтаксис запроса ORM и уменьшите возможное снижение производительности (вы действительно тестировали более сложный запрос для видите, что он медленнее?)

1
ответ дан 4 December 2019 в 13:47
поделиться

Django будет рассматривать NULL как объект Python None , поэтому:

Person.objects.filter(company = None)
0
ответ дан 4 December 2019 в 13:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: