У меня есть тест, который я пытаюсь пройти:
@pytest.fixture(scope='function')
@pytest.mark.usefixtures('db')
def new_scan_service(db):
user = User.create(username='Princess Leia', email='dontatme@me.com')
date = datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p')
experiment1 = Experiment.create(date=date, scanner='GE', num_scans=2, user_id=user.id)
experiment2 = Experiment.create(date=date, scanner='GE', num_scans=2, user_id=user.id)
db.session.commit()
print('I just put the user and two experiments into the database', user.num_experiments)
s = ScanService(user.id, experiment2.id)
return s
class TestScanUpload:
def test_xnat_ids_correctly_generated_for_multiple_experiments_and_scans(self, new_scan_service):
"""
Given a subject with more than one experiment, and an experiment with more than one scan
When xnat ids are generated
Then test that xnat_experiment_id and xnat_scan_id are as expected
"""
with open('<file-path>', 'r') as f:
xnat_ids = new_scan_service._generate_xnat_identifiers()
assert xnat_ids['experiment']['xnat_id'] == '000001_MR2'
user.num_experiments
должен увеличиваться на единицу каждый раз, когда я получаю новый эксперимент. Я где-то читал о переполнении стека, что это было быстрее, чем делать запрос каждый раз, когда вы хотели узнать, сколько экспериментов проводит пользователь.
Я пытаюсь использовать sqlachemy.event
, чтобы прослушать создание эксперимента и обновить user.num_experiments
.
Вот одна вещь, которую я попробовал. Я поместил этот код в модуль, который определяет модель эксперимента:
def update_user_exp_count(mapper, connection, target):
db.session.begin_nested()
user_id = target.user_id
print("user id is ", user_id)
user = User.get_by_id(user_id)
user.num_experiments += 1
print("This is my listener. user.num experiments is", user.num_experiments)
db.session.add(user)
db.session.commit()
event.listen(Experiment, 'before_insert', update_user_exp_count)
Тест не пройден с ошибкой подтверждения, и вот мой стандартный вывод:
user id is 1
This is my listener. user.num experiments is 1
user id is 1
This is my listener. user.num experiments is 1
I just put the user and two experiments into the database. user.num_experiments is 0
Итак, мой слушатель был вызван, но объект пользователя никогда не обновлялся в таблице базы данных постоянным способом.
Я также пытался следовать примеру из этого вопроса .
Вот соответствующая часть модели User.
class User(UserMixin, SurrogatePK, Model):
"""A user of the app."""
__tablename__ = 'users'
username = Column(db.String(80), unique=True, nullable=False)
email = Column(db.String(80), unique=True, nullable=False)
num_experiments = Column(db.Integer(), default=0)
experiments = relationship('Experiment', backref='user', lazy='dynamic')
И модели эксперимента (reference_col
- это функция, определенная в колбе печенья для вставки внешних ключей):
class Experiment(SurrogatePK, Model):
"""A user's experiment, during which they are scanned."""
__tablename__ = 'experiments'
date = Column(db.Date(), nullable=False)
scanner = Column(db.String(80), nullable=True)
num_scans = Column(db.Integer(), nullable=True)
user_id = reference_col('users', nullable=True)
Я поместил этот код в модуль, который определяет модель пользователя:
@event.listens_for(User.experiments, 'append')
def receive_append(target, value, initiator):
print("I was executed")
target.num_experiments += 1
Это никогда не выполняется.
Что мне нужно сделать, чтобы родитель слушал новых детей и обновлялся, когда получал их? Буду признателен за любую помощь.
ОБНОВЛЕНИЕ: я разработал способ обойти эту проблему. Но мне все еще интересно знать, почему я не могу использовать слушателей. Вот мой обходной путь:
class ExperimentService:
def add(self, user, date, scanner, num_scans):
exp = Experiment.create(date=date, scanner=scanner, num_scans=num_scans, user_id=user.id)
user.update(num_experiments=user.num_experiments + 1)
print("here I am in the add function. user.num_experiments is ", user.num_experiments)
return exp
.update
- это один из удобных методов, предоставляемых колбой для печенья. Когда я делаю это, мой тест проходит. Итак, мои оставшиеся вопросы:
Почему, хотя update_user_exp_count
выполняется, изменения не сохраняются в базе данных?
и
Почему receive_append
никогда не выполняется?