У меня есть три таблицы [MySQL]: Person, Role, PersonRole
class Person(Base):
__tablename__ = 'people'
id = Column(INTEGER(unsigned=True), primary_key=True)
full_name = Column(String(120), nullable=False)
email = Column(String(128))
username = Column(String(50))
last_modified = Column(TIMESTAMP, nullable=False,
server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
created = Column(TIMESTAMP, server_default=text('CURRENT_TIMESTAMP'))
roles = relationship('Role',
secondary='person_role',
primaryjoin="and_(Person.id==PersonRole.person_id,"
"Role.active==True,"
"PersonRole.active==True)",
back_populates='people')
def __repr__(self):
"""String representation."""
return '''<Person(id='%s', full_name='%s')>''' % (
str(self.id), str(self.full_name)
)
class Role(Base):
__tablename__ = 'role'
id = Column(INTEGER(unsigned=True), Sequence('role_id_seq'), primary_key=True)
role_name = Column(String(16))
active = Column(Boolean, default=True)
last_modified = Column(TIMESTAMP, nullable=False,
server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
created = Column(TIMESTAMP, server_default=text('CURRENT_TIMESTAMP'))
users = relationship('Person',
secondary='person_role',
primaryjoin="and_(Role.id==PersonRole.role_id,"
"Role.active==True,"
"PersonRole.active==True)",
back_populates='roles')
def __repr__(self):
"""String representation."""
return '''<Role(role_id='%s', role_name='%s')>''' % (
str(self.role_id), str(self.role_name)
)
class PersonRole(Base):
__tablename__ = 'person_role'
ds_id = Column(INTEGER(unsigned=True),
ForeignKey('person.id'), primary_key=True)
role_id = Column(INTEGER(unsigned=True),
ForeignKey('role.id'), primary_key=True)
active = Column(Boolean, default=True)
last_modified = Column(TIMESTAMP, nullable=False,
server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
created = Column(TIMESTAMP,
server_default=text('CURRENT_TIMESTAMP'))
Получение человека примерно так:
... настройка сеанса как s
...
person = s.query(Person).get(123)
и перечислить их роли:
for role in person.roles:
print(role.id, role.role_name, role.active)
Теперь в каждой таблице есть столбец active
. Это необходимо для отслеживания активного состояния [шокера], так как мы не хотим удалять данные из таблицы, просто сохраняем их состояние. Теперь о двух проблемах, которые не позволяют мне использовать SQLAlchemy в целом и заставляют меня писать и выполнять SQL вручную -
- Часть
active
в последнем цикле отображает активное состояние role.active
, а не фактическое состояние person_role.active
.
- Удаление роли приведет к удалению строки отношения вместо выполнения требуемого действия,
person_role.active = 0
- Даже если я деактивирую отношения, добавление их снова приведет к ошибке
Duplicate Key
.
Есть ли разумный, действительный способ выполнить это без реструктуризации моих данных?
Изменить для уточнения:
В этом случае основными таблицами являются person
и person_role
. Персона - это главная таблица, в которой находятся наши пользователи. PersonRole выполняет роли, которые фактически выполняет человек, в форме от person.id
до role.id
. Таблица ролей - это просто таблица поиска для определения роли (для получения имен).
Полагаю, что я хочу, это способ перехвата того, как ORM фактически добавляет / удаляет данные. Добавление должно [более или менее] делать «upsert», а удаление должно, в основном, запускать запрос на обновление, например: update person_role set active = 0 where person_id = %s and role_id = %s
.
Я прочитал много документов, но, как правило, теряюсь в терминологии. : S