ForeignKeyViolation при вызове delete для объекта - каскад 'all delete', не удаляющий ссылочные объекты - PullRequest
1 голос
/ 03 марта 2020

Когда у меня есть экземпляр User, и я пытаюсь вызвать db.delete(user), я получаю ForeignKeyViolation. Я ожидаю, что объекты adminrelationship_channel_id также будут удалены, но, похоже, это не так. Когда я удаляю свой объект User, я хочу, чтобы связанные с ним объекты AdminRelationship также удалялись.

В базе AdminRelationship объект 'User' может иметь тип 'type = channel'. Отсюда следует, что пользователи должны быть администраторами других пользователей.

>>> channel = db.query(User).filter_by(type='channel').first()
>>> db.delete(channel)
>>> db.commit()

sqlalchemy.exc.IntegrityError: (psycopg2.errors.ForeignKeyViolation) update or delete on
 table "user" violates foreign key constraint "adminrelationship_channel_id_fkey" on tab
le "adminrelationship"
DETAIL:  Key (id)=(12) is still referenced from table "adminrelationship".
class User(Base):
    __tablename__ = 'user'
    admins = Column(String(5000), index=True)
    channels = relationship('AdminRelationship',
                            primaryjoin=(AdminRelationship.admin_id == id),
                            backref=backref('owner', cascade="save-update, delete"),
                            lazy='dynamic',
                            cascade='all, delete')
    user_trading_settings = Column(Enum(schemas.UserTradingChoices), default=schemas.UserTradingChoices.auto)
    channel_publish_settings = Column(Enum(schemas.PublishSettingsChoices), default=schemas.PublishSettingsChoices.all)
    is_authenticated = Column(Boolean(), default=True)

class AdminRelationship(Base):
    __tablename__ = 'adminrelationship'
    id = Column(Integer, primary_key=True)
    admin_id = Column(Integer, ForeignKey('user.id'))
    channel_id = Column(Integer, ForeignKey('user.id'))
    admin = relationship("User", foreign_keys=[admin_id], cascade='delete')
    channel = relationship("User", foreign_keys=[channel_id], cascade='delete')

    def __repr__(self):
        return f'{self.admin.username} is an owner of {self.channel.username}'


...