Flask-SQLAlchemy 验证:防止添加到基于其他字段的关系

Flask-SQLAlchemy validation: prevent adding to relationship based on other field

我正在使用 flask-sqlalchemy 并尝试验证对我的数据库的输入。对于单个字段,验证装饰器效果很好。但是,我遇到了阻止将值添加到基于另一个字段的值的 collection/relationship 的问题。例如,考虑以下数据模型:

class MyRelation(db.Model):
    __tablename__ = "my_relation"
    id = db.Column(db.Integer, primary_key=True)
    my_data_id = db.Column(db.Integer, db.ForeignKey("my_data.id"))
    some_value = db.Column(db.String)

class MyData(db.Model):
    __tablename__ = "my_data"
    id = db.Column(db.Integer, primary_key=True)
    some_relation = db.relationship("MyRelation", backref="my_data")
    some_other_value = db.Column(db.Boolean)

我 运行 遇到的问题是,如果 some_other_value == True,我想确保 some_relation 为空。我研究了以下选项。我不确定是否可以调整其中任何一个以提供预期的功能:

  1. 对多个字段使用 @validates 作为 。这种方法的问题是它似乎是一个一个地验证集合,并在验证中返回 None 格式不正确的输入产量 sqlalchemy.orm.exc.FlushError: Can't flush None value found in collection Job.alternate_attributes。返回一个空列表也不起作用。
  2. 使用 before_insert 事件侦听器,如 outlined here. The challenge I see with this is this seems like this would not be compatible with relationship events per the official docs
  3. 使用 before_flush 事件监听器,听起来它可能与这个用例兼容,但老实说,我很难找到一个很好的例子来说明如何使用它鉴于我的目标。它非常抽象,我在文档中没有看到任何示例(both of the examples mentioned at the end of the before_flush section 实际上不包含对他们应该演示的 before_flush 方法的任何引用)。

任何指导将不胜感激 - 谢谢!

回答我自己的问题 - before_flush 事件侦听器是去这里的方法:

@db.event.listens_for(db.session, 'before_flush')
def validate_and_modify_relationships(session, flush_context, instances):
    """
    Complex validation that cannot be performed with @valdiates
    """
    
    # new records only (for updates only, use session.dirty)
    for instance in session.new:
        if isinstance(instance, MyData):
            if instance.some_other_value:
                instance.some_relation = []

按预期工作,我唯一不介意的是它是否可以作为 MyData class 上的方法与我的其余 @validates 方法一起使用,但是这个否则相当清楚。