Автоматически распространяющее удаление при использовании двунаправленной ассоциации_proxy

Я использую двунаправленную association_proxy для связывания свойств Group.members и User.groups . У меня проблемы с удалением члена из Group.members . В частности, Group.members.remove успешно удалит запись из Group.members , но оставит None вместо соответствующей записи в User.groups .

Более конкретно, следующий (минимально-ишевой) репрезентативный фрагмент кода не выполняет свое последнее утверждение:

 import sqlalchemy as sa from sqlalchemy.orm import Session from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Group(Base): __tablename__ = 'group' id = sa.Column(sa.Integer, autoincrement=True, primary_key=True) name = sa.Column(sa.UnicodeText()) members = association_proxy('group_memberships', 'user', creator=lambda user: GroupMembership(user=user)) class User(Base): __tablename__ = 'user' id = sa.Column(sa.Integer, autoincrement=True, primary_key=True) username = sa.Column(sa.UnicodeText()) groups = association_proxy('group_memberships', 'group', creator=lambda group: GroupMembership(group=group)) class GroupMembership(Base): __tablename__ = 'user_group' user_id = sa.Column(sa.Integer, sa.ForeignKey('user.id'), primary_key=True) group_id = sa.Column(sa.Integer, sa.ForeignKey('group.id'), primary_key=True) user = sa.orm.relationship( 'User', backref=sa.orm.backref('group_memberships', cascade="all, delete-orphan")) group = sa.orm.relationship( 'Group', backref=sa.orm.backref('group_memberships', cascade="all, delete-orphan"), order_by='Group.name') if __name__ == '__main__': engine = sa.create_engine('sqlite://') Base.metadata.create_all(engine) session = Session(engine) group = Group(name='group name') user = User(username='user name') group.members.append(user) session.add(group) session.add(user) session.flush() assert group.members == [user] assert user.groups == [group] group.members.remove(user) session.flush() assert group.members == [] assert user.groups == [] # This assertion fails, user.groups is [None] 

Я попытался следовать ответам на отношения SQLAlchemy с проблемами association_proxy и как SQLAlchemy association_proxy можно использовать в двух направлениях? но они, похоже, не помогают.

One Solution collect form web for “Автоматически распространяющее удаление при использовании двунаправленной ассоциации_proxy”

Я обнаружил вашу проблему почти полностью случайно, так как я пытался выяснить, что происходит.

Поскольку в db не было данных, я добавил session.commit() . Оказывается, что (из связанного ответа):

Эти изменения не сохраняются постоянно на диске или видимы для других транзакций, пока база данных не получит COMMIT для текущей транзакции (что и делает session.commit ()).

Поскольку вы просто .flush() процессе изменений, sqlalchemy никогда не запрашивает базу данных повторно. Вы можете проверить это, добавив:

 import logging logging.getLogger('sqlalchemy').setLevel(logging.INFO) logging.getLogger('sqlalchemy').addHandler(logging.StreamHandler()) 

А затем просто запустите свой код. Он отобразит все запросы, которые запускаются по мере их возникновения. Затем вы можете изменить session.flush() на session.commit() а затем повторно запустить, и вы увидите, что несколько SELECT запускаются после вашей commit .

Похоже, что session.expire(user) или session.refresh(user) также заставит обновить пользователя. Я не уверен, есть ли способ заставить обновление распространяться на другой объект, не будучи явно о нем (или если это даже желательно).

  • Текстовое поле Readonly в Flask-Admin ModelView
  • ArgumentError: отношения ожидают аргумент класса или сопоставления
  • SQLAlchemy - интроспекция ORM-классов / объектов
  • Многие-ко-многим в sqlalchemy. Предотвращение вставки SQLAlchemy в таблицу, если тег уже существует
  • Расширенный SQL-запрос с подзапросами, группировка, подсчет и сумма функций в SQLalchemy
  • Создание баз данных в тестах SQLAlchemy с помощью PostgreSQL
  • Как фильтровать в `sqlalchemy` строку длиной?
  • сигналов или триггеров в SQLAlchemy
  • Как подсчитать строки с помощью SELECT COUNT (*) с помощью SQLAlchemy?
  • Могу ли я использовать pyodbc / freetds и sqlalchemy с десятичными данными в mssql?
  • динамическое сопоставление sqlalchemy
  •  
    Interesting Posts for Van-Lav

    Python paramiko script, проблемы с чтением вывода во время exec_command ()

    Будет ли результат numpy.as_strided зависеть от входного dtype?

    Музыкальное распознавание и обработка сигналов

    Как передать ссылку на очередь на функцию, управляемую пулом.map_async ()?

    Программный поворот монитора

    Применение параметров tinyMCE для динамически созданного текстового поля

    Инициализировать список до определенной длины в Python

    Изменение рюкзака … в python

    у python есть конструктор списка?

    Объедините два фрейма данных pandas pythas разной длины, но сохраните все строки в кадре выходных данных

    Что такое питонический способ доступа к вложенным dicts без ошибок NoneType

    Использует ли модуль подпроцесса выпуск python GIL?

    объединить два кадра данных без повторов pandas

    Python Regex – Предложение не включает строки

    Регулярное выражение для замены некоторых точек запятыми в комментариях клиентов

    Python - лучший язык программирования в мире.