2016-11-23 3 views
2

Я пытаюсь запросить все объекты в таблице без обратных ссылок из другой модели.Фильтрация на обратных ссылках Django

class A(models.Model): 
    pass 

class B(models.Model): 
    reference = models.ForeignKey(A) 

Для того, чтобы получить все A объекты без каких-либо ссылок от любых B объектов, я

A.objects.filter(b__isnull=True) 

Django documentation on isnull не упоминает обратные ссылки на всех.

Могу ли я попасть в неприятности с этим или это плохо документировано?

+1

Я не могу придумать причины, по которым это не сработает, [Этот вопрос] (http://stackoverflow.com/q/21405658/1324033) кажется, что он правильный – Sayse

ответ

2

Я попробовал это с Django 1.10.3, используя тот же пример кода.

Давайте посмотрим на сырье заявление SQL, что Django создает:

>>> print(A.objects.filter(b__isnull=True).query) 
SELECT "backrefs_a"."id" FROM "backrefs_a" LEFT OUTER JOIN "backrefs_b" ON ("backrefs_a"."id" = "backrefs_b"."reference_id") WHERE "backrefs_b"."id" IS NULL 

Технически, это не тот же самый SQL, что Django будет посылать в базу данных, но это достаточно близко. Более подробное обсуждение см https://stackoverflow.com/a/1074224/5044893

Если мы довольно его вверх немного, вы можете увидеть, что запрос является на самом деле вполне безопасно:

SELECT "backrefs_a"."id" 
FROM "backrefs_a" 
LEFT OUTER JOIN "backrefs_b" ON ("backrefs_a"."id" = "backrefs_b"."reference_id") 
WHERE "backrefs_b"."id" IS NULL 

LEFT в LEFT OUTER JOIN гарантирует, что вы получите записи из A, даже если нет совпадающих записей в B. И поскольку Django не сохранит B с NULLid, вы можете быть уверены, что он будет работать так, как вы ожидаете.