flask-sqlachemy:无法让父级监听和更新对子级所做的更改

时间:2018-11-06 13:22:07

标签: python events flask sqlalchemy flask-sqlalchemy

我要通过一项测试:

@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应该增加一。我在Stack Overflow上的某个地方读到,每当您想知道用户进行了多少次实验时,这比执行查询要快。

我正在尝试使用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

因此调用了我的侦听器,但从未以持久的方式在数据库表中更新用户对象。

我也尝试遵循this question中的示例。

这是用户模型的相关部分。

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是在cookiecutter烧瓶中定义的用于插入外键的函数):

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是cookiecutter flask提供的一种便捷方法。当我这样做时,我的测试通过了。所以我剩下的问题是:

为什么即使执行了update_user_exp_count,更改似乎也不会持久保存在数据库中?

为什么receive_append从未执行过?

0 个答案:

没有答案