В двух словах: мои модели B -> A <- C </strong>, я хочу отфильтровать Bs , где существует хотя бы один C ,удовлетворяющих некоторым произвольным условиям и относящимся к тем же A , что и B .Также приветствуется помощь по некоторым усложняющим факторам (см. Ниже).
Подробности:
Я пытаюсь создать универсальную модель для ограничения доступа пользователей к строкам в других моделях.Вот (упрощенный) пример:
class CanRead(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
class Direct(models.Model):
...
class Indirect(models.Model):
direct = models.ForeignKey(Direct)
...
class Indirect2(models.Model):
indirect = models.ForeignKey(Indirect)
...
Невозможно связать CanRead с каждой строкой в каждой модели (слишком дорого в пространстве), поэтому ожидается, что только некоторые модели будут иметьэта ассоциация (как Direct выше).В этом случае вот как я могу увидеть, доступен ли пользователю Direct или нет:
Direct.objects.filter(Q(canread__user=current_user), rest_of_query)
(К сожалению, этот запрос не будет работать - в 1.2.5по крайней мере - из-за общего fk, любая помощь с этим была бы признательна, но есть обходные пути, реальная проблема заключается в том, что будет дальше)
Доступность других будет продиктована их отношениями с другими моделями.Таким образом, Косвенный будет доступен пользователю, если прямой доступен, и Косвенный2 будет, если косвенный__direct и т. Д.
Моя проблема в том, как я могу сделать этот запрос?Я испытываю желание написать что-то вроде:
Indirect.objects.filter(Q(canread__content_object=F('direct'), canread__user=current_user), rest_of_query)
Indirect2.objects.filter(Q(canread__content_object=F('indirect__direct'), canread__user=current_user), rest_of_query)
, но это не работает (Django ожидает связь между CanRead и Косвенным - что несуществует - для обратного запроса на работу).Если бы я писал это прямо на SQL, я бы сделал что-то вроде:
SELECT *
FROM indirect i
JOIN direct d ON i.direct = d.id
JOIN canread c ON c.object_id = d.id
WHERE
c.content_type = <<content type for Direct>> AND
c.user = <<current user>> AND
<<rest_of_query>>
, но я не могу перевести этот запрос в Django.Является ли это возможным?Если нет, то каков был бы наименее навязчивый способ сделать это (используя как можно меньше необработанного SQL)?
Спасибо за ваше время!
Примечание. Упомянутый обходной путь будет не использоватьgeneric fk ... :( Я могу отказаться от CanRead модели и иметь множество CanReadDirect , CanReadDirect2 , CanReadDirect3 и т. д. Этонезначительные хлопоты, но не слишком мешают моему проекту.