2016-03-17 5 views
2

У меня есть следующие сущности, каждая из которых представляет собой таблицу в моей базе данных:sqlalchemy- три организации присоединились через одну таблицу

User 
Application 
Role 

Я еще одна таблица под названием «user_app_role», который выглядит следующим образом:

table user_app_role(
user_id int not null , 
application_id int not null, 
role_id int not null, 
primary key(user_id, application_id, role_id) 
) 

где user_id, application_id и role_id - все внешние ключи в таблицах пользователя, приложения и ролей.

Запись в этой таблице указывает, что пользователь имеет определенную роль в конкретном приложении, поэтому строка может возвращать 1, 1, 1, указав, что пользователь 1 имеет роль 1 в приложении 1. Аналогично, 1, 2, 1 будет означать, что пользователь 1 также имеет роль 2 в приложении 1.

У меня есть сопоставления sqlalchemy, определенные для пользователя, приложения и роли. Я хотел бы, чтобы объект User каким-то образом имел список объектов приложения и для каждого объекта приложения, этот объект будет содержать список объектов Role.

Из чтения документации по sqlalchemy, похоже, этот тип отношений невозможно сопоставить, и я нашел только несколько других вопросов о stackoverflow, где это было задано, ни один из которых не имеет ответа. Это похоже на относительно нормальное отношение базы данных 3NF (у меня 4 из них в моей модели данных), можно ли как-то установить это в sqlalchemy? Я мог бы сделать все это в чистом SQL за 10 минут, но я не хочу выбрасывать всю другую полезную функцию SqlAlchemy, но если я не могу сделать это как-то работать, то мое приложение не сможет отправить.

Кроме того, ПОЖАЛУЙСТА, НЕ ПРЕДУСМАТРИВАЙТЕ, что я просто изменяю свою модель данных или денормализую базу данных или каким-либо образом обманываю ее. Ответы такого характера мне не помогут. Я рад изменить мою объектную модель или добавить дополнительные объекты, если мне нужно каким-то волшебным образом отобразить эту таблицу на 2 объекта или что-то странное, но я не могу изменить модель данных.

+0

Я до сих пор не нашел подходящего решения для этого, но я создал отдельный объект UserAppRole и использовал отношения в объекте User, чтобы присоединиться к UserAppRole. Поскольку я могу загружать объекты Application и Role (и их очень мало), то мой уровень persistence просто подключает значения вручную в тех очень редких случаях, когда идентификатора недостаточно (в основном для отображения в пользовательском интерфейсе где-то). Я отправлю ответ с более подробной информацией, если не получу лучшего ответа в течение следующих нескольких дней. –

ответ

0

Хорошо, насколько я могу судить, создание фактического отображения этого сценария невозможно в SQLAlchemy так вот мой обходной путь:

class UserAppRole(Base): 
    __tablename__ = 'userapprole' 
    user_id = Column(stuff, ForeignKey(users.id)) 
    role_id = Column(otherstuff, ForeignKey(roles.id)) 
    app_id = Column(morestuff, ForeignKey(apps.id)) 

Я решил, что в области моего приложения, пользователь имеет роли с приложениями, поэтому отношения для этого нового объекта будет на пользователя:

class User(Base): 
    __tablename__ = 'users' 
    approles = relationship(UserAppRole, backref=backref('app_user_role', uselist=True)) 
    # other columns, relationships, etc. 

Это хорошо работает, потому что когда я загружаю пользователя, я хочу знать, какие приложения имеют доступ к каким-либо образом, и я хотите знать, какие роли у них есть для этих приложений. В моем домене роль - это вещь, и приложение тоже есть вещь, и относительно мало таких вещей, и они, как правило, не меняются (хотя это не является требованием для этого решения). Важно то, что я могу загружать объекты приложения и роли по их идентификатору, который достаточно удобен мне сейчас в моем списке одобрений в объекте User.

Чтобы связать это все вместе, последнее, что я делаю, это использовать репозиторий для обработки персистентности для объектов User. Когда я загружаю пользователя, SqlAlchemy заполняет список совпадений идентификаторами. Затем я могу вручную загрузить приложения и роли и построить словарь для приложений со списком ролей. Теперь, когда я добавляю роль для пользователя в приложение, мне нужно передать объект Application (который знает, какие роли действительны) и объект Role (который может или не может быть действительным для этого приложения). Оба из них будут иметь идентификаторы, поэтому для меня довольно тривиально обновлять список словарей и/или одобрений, чтобы содержать то, что я хочу.В маловероятном случае, когда я пытаюсь записать в БД с идентификатором роли или идентификатором приложения, которого не существует, ограничения в моей базе данных отклонят вставку/обновление, и я получу исключение.

Это не мое идеальное решение, но оно отлично подходит для двух ситуаций, с которыми я сталкиваюсь. Если у кого-то есть лучшее решение, пожалуйста, отправьте его. Я считаю, что сложные списки смежности должны быть полезны для этого сценария, но текущая документация SqlAlchemy, по-видимому, указывает на то, что они должны быть для таблиц саморегуляции, и я не нашел способ сделать эту работу для этого конкретного сценария.

Смежные вопросы