SQLAlchemy и сложные запросы - PullRequest
1 голос
/ 02 июня 2010

Я должен реализовать ACL для существующего приложения.
Поэтому я добавил в базу данных таблицу user , group и groupmembers .
Я определил отношение ManyToMany между user и group через таблицу ассоциации groupmembers .
Чтобы защитить некоторые ресурсы приложения (например, item ), я добавил дополнительную таблицу ассоциации auth_items , которую следует использовать в качестве таблицы ассоциации для отношения ManyToMany между группы / пользователи и конкретный элемент .

элемент имеет следующие столбцы:

  • user_id -> таблица пользователей
  • group_id -> таблица групп
  • item_id -> таблица элементов
Установлено

по крайней мере для user_id и group_id . Таким образом, можно определить доступ для группы или пользователя к определенному элементу.

Я использовал AssociationProxy для определения отношений между пользователями / группами и элементами.

Теперь я хочу отобразить все элементы, к которым у пользователя есть доступ, и мне очень трудно это сделать. Используются следующие критерии:

  • Все элементы, принадлежащие пользователю, должны быть показаны (item.owner_id = user.id)
  • Должны быть показаны все публичные элементы (item.access = public)
  • Должны быть показаны все элементы, к которым у пользователя есть доступ (auth_item.user_id = user.id)
  • Должны быть показаны все элементы, к которым имеет доступ группа пользователя.

Первые три критерия довольно просты, но мне трудно выполнить четвертый.

Вот мой подход:

clause = and_(item.access == 'public')
if user is not None:
   clause = or_(clause,item.owner == user,item.users.contains(user),item.groups.contains(group for group in user.groups))

Третий критерий дает ошибку.

item.groups.contains(group for group in user.groups)

Я на самом деле не уверен, что это вообще хороший подход.
Каков наилучший подход при фильтрации множества отношений?
Как я могу отфильтровать множество отношений на основе другого списка / отношения?

Кстати, я использую последнюю версию sqlalchemy (6.0) и эликсира

Спасибо за любые идеи.

1 Ответ

1 голос
/ 03 июня 2010

contains() метод для проверки одного элемента. Предполагая, что ваша групповая таблица сопоставлена ​​с Group class, попробуйте следующее:

item.groups.any(Group.id.in_([group.id for group in user.groups])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...