Как я могу фильтровать по нескольким условиям NOT в ORM Django?

В Django 3.2 у меня есть следующие модели:

class Person(models.Model):
    name = models.CharField(max_length=100)

class Employment(models.Model):
    owner = models.ForeignKey('Person', on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    full_time = models.BooleanField(default=True)

class Car(models.Model):
    owner = models.ForeignKey('Person', on_delete=models.CASCADE)
    color = models.CharField(max_length=100)

Цель: Give me all people that drive a red car (unless they're a full-time firefighter)

Вот то, что, как я думал, будет работать:

Person.objects.filter(
    ~Q(employment__title='firefighter', employment__full_time=True),
    car__color='red'
)

Однако, это порождает следующий SQL:

SELECT *
FROM "person"
INNER JOIN "car" ON ("person"."id" = "car"."owner_id")
WHERE "car"."color" = red
  AND (
    NOT (
      EXISTS(
        SELECT (1) AS "a"
        FROM "employment" U1
        WHERE U1."full_time"
          AND U1."owner_id" = "person"."id"
      )
      AND EXISTS(
        SELECT (1) AS "a"
        FROM "employment" U1
        WHERE U1."title" = firefighter
          AND U1."owner_id" = "person"."id"
      )
    )

Это фактически возвращает всех людей, которые водят красный автомобиль (если они не являются пожарными ИЛИ имеют постоянную работу). Как и во всех других ключах фильтра, я ожидал, что эти два условия на внешнем отношении будут ИДЕЙНЫМИ.

Почему такое неожиданное поведение? Как правильно написать это, чтобы sql выглядел следующим образом:?

SELECT *
FROM "person"
INNER JOIN "car" ON ("person"."id" = "car"."owner_id")
WHERE "car"."color" = red
  AND (
    NOT (
      EXISTS(
        SELECT (1) AS "a"
        FROM "employment" U1
        WHERE U1."full_time",
          AND U1."title" = firefighter
          AND U1."owner_id" = "person"."id"
      )
    )
   

Можно не смешивать Q() и **kwargs в filter():

Person.objects.filter(
    ~Q(employment__title='firefighter', employment__full_time=True) &
    Q(car__color='red')
)
Вернуться на верх