Можете ли вы выбрать все существующие в django?
Я создаю менеджер доступа для контроля взаимодействия с API в моем приложении. У меня есть модель, которая представляет пользователя, имеющего доступ к данному экземпляру модели, она выглядит следующим образом:
class Permission(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
Менеджер доступа знает об иерархии моделей и может понять, что если вы пытаетесь просмотреть или изменить данный тип объекта с данным ID, то он может проверить, есть ли у вас разрешения на него или на родительскую сущность в дереве. Он создает Q-объекты и обращается к базе данных с запросом о наличии соответствующего разрешения для пользователя.
Я столкнулся с новым случаем использования, когда определенная сущность имеет двух родителей в дереве, и мне нужно, чтобы менеджер доступа проверял, что пользователь имеет разрешения где-то на одной обе стороне дерева.
Вот (санированный) объект Q, который, как я думал, является тем, что мне нужно:
<Q:
(AND:
(OR:
(AND: ('content_type', <ContentType: myapp | foo>), ('object_id', 676)),
(AND: ('content_type', <ContentType: myapp | bar>), ('object_id', 634)),
(AND: ('content_type', <ContentType: myapp | wibble>), ('object_id', 1))
), (OR:
(AND: ('content_type', <ContentType: myapp | foo>), ('object_id', 2)),
(AND: ('content_type', <ContentType: myapp | bar>), ('object_id', 633)),
(AND: ('content_type', <ContentType: myapp | wibble>), ('object_id', 2))
)
)
>
Предположим, что Foo является родителем Bar (Bar имеет FK к Foo), а Bar является родителем Wibble (Wibble FK к Bar). То есть, на словах, я пытаюсь проверить:
- The user has access to ANY of:
- Foo with id 676
- Bar with id 634
- Wibble with id 1
- AND that the user ALSO has access to ANY of:
- Foo with id 2
- Bar with id 633
- Wibble with id 2
т.е. имеет ли пользователь доступ к обоим вибблам, или к любым родителям обоих вибблов.
Вот текущие данные в соответствующей таблице БД
SELECT * FROM myapp_permission;
id | object_id | content_type_id | user_id
------+-----------+-----------------+---------
1181 | 676 | 30 | 316740
1182 | 633 | 29 | 316740
Итак (просто поверьте мне на идентификаторы ContentType) пользователь действительно имеет доступ к Foo с ID 676 и Bar с ID 633, так что у пользователя есть разрешения с обеих сторон. Но вышеупомянутый объект Q при применении выглядит следующим образом:
Permission.objects.filter(the_q_object).exists()
... возвращает False. Я понял, что это происходит потому, что запрос запрашивает ОДИН ряд, удовлетворяющий обоим критериям, вместо 2 (или более) рядов, которые сочетаются удовлетворяют им.
Итак, после всего этого контекста возникает вопрос: как я могу изменить объект Q, чтобы выполнить нужный мне запрос?