Доступ к отношениям внутри обработчиков событий after_insert и before_insert при использовании SQLAlchemy - PullRequest
0 голосов
/ 20 сентября 2019

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

1) edit Я пытаюсь добавить прослушиватель событий для объекта Record, чтобы сделать что-то дляpeople в экземпляре записи после того, как он был создан инициализатором записи по умолчанию.Единственная проблема - target в теле do_action не добавлен список people, тогда как список people присутствует после создания экземпляра.В чем причина этого и есть ли обходной путь для do_action?

Моя модель:

record_structure = db.Table(
    'record_structure',
    db.Column('person_id', db.Integer, db.ForeignKey('person.id')),
    db.Column('record_id', db.Integer, db.ForeignKey('record.id')))

class Person(db.Model):
    __tablename__ = 'person'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, nullable=False)

class Record(db.Model):
    __tablename__ = 'record'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, nullable=False)
    people = db.relationship('Person', secondary=record_structure)

    def __init__(self, name, people):
        self.name = name
        self.people = list()
        self.people.extend(people)

@db.event.listens_for(Record, 'after_insert')
def do_action(mapper, connection, target):
    print(target.name) # output 'my record'
    print(len(target.people)) # output: 0 ??
    # do something with target.people

Мой load_db.py

p1 = Person(name='tom')
p2 = Person(name='fred')
db.session.add(p1)
db.session.add(p2)
db.session.commit()
r = Record('my record', [p1, p2])
print(len(r.people)) # output: 2
db.session.add(r)
db.session.commit()

2) Если естьэто обходной путь для ловушки события after_insert.Есть ли обходной путь, если я заменю ловушку на ловушку события before_insert?

1 Ответ

0 голосов
/ 21 сентября 2019

Получается, что код, который я предоставил в 1), вполне подходит, поэтому len(target.people) == 2 и 2) также выполняются.Мой оригинальный код немного отличался, и это вызвало len(target.people) == 0.bookkeeper.records.append(self), кажется, вызвал преждевременную вставку и инициализировал self.people как пустой список.Спасибо @SuperShoot за попытку воспроизвести его.

class Record(db.Model):
    __tablename__ = 'record'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, nullable=False)
    people = db.relationship('Person', secondary=record_structure)

    def __init__(self, name, bookkeeper, people):
        self.name = name
        bookkeeper.records.append(self)
        self.people = list()
        self.people.extend(people)

Полагаю, хорошей практикой является помещать строки, которые проходят self, как bookkeeper.records.append(self), в конце __init__, чтобы соответствующие данные передавались событиюкрючки.

...