sqlalchemy - 关系上的“验证”不会在分配事件上发出

问题描述 投票:0回答:1

使用

sqlalchemy
考虑以下内容:

from sqlalchemy.orm import validates

class DeviceTestResult:
    __tablename__ = "device_test"

    passed: bool = mapped_column(default=False, init=False)
    failure_modes: Mapped[list['FailureMode']] = relationship(default_factory=list, back_populates='test')

    @validates('failure_modes')
    def validate_failure_modes(self, key, failure_mode):
        """
        Validator for failure modes. When attribute is changed, updates passed to be false if there are any fails.
        """
        currently_passes = all([fm.passed for fm in self.failure_modes])
        self.passed = all([fm for fm in [currently_passes, failure_mode.passed]])
        return failure_mode


class FailureMode:
    __tablename__ = "failure_mode"
    
    passed: bool = mapped_column()
    test: Mapped['DeviceTestResult'] = relationship(back_populates='failure_modes', default=None)
    completed_at: datetime = mapped_column(insert_default=datetime.now(), default=datetime.now())

    @validates('passed')
    def validate_test(self, key, passed):
        """
        validator for passed. Updates associated test object status
        """
        if self.test:
            currently_passes = all([fm.passed for fm in self.test.failure_modes])
            self.test._passed = all([fm for fm in [currently_passes, passed]])
        return passed

# Case 1 - append, emits validate_failure_modes
device_test = DeviceTest()
failure_mode = FailureMode()
device.failure_modes.append(failure_mode)

# Case 2 - assignment, does not emit validate_failure_modes
device.failure_modes = [failure_mode]

validate_failure_modes
在情况 1 中会发出,但在情况 2 中不会发出。

案例2如何获得验证?如果这是不可能的,我如何限制用户使用分配设置属性,以便他们可以通过附加进行修改?

我尝试过使用

sqlalchemy
描述符和混合,但还没有成功。

python python-3.x sqlalchemy
1个回答
0
投票

问题不在于验证器没有在列表中的每个项目上运行(它是)——它与验证完成的顺序有关。

为了提供一些上下文,我有一个 device_test 对象和一个 failure_mode 对象。 device_test 可以有多种不同的故障模式,如果添加了未通过的 failure_mode,则 device_test 也不应该通过。

类DeviceTestResult: 表名 =“device_test” 计数 = 0

passed: bool = mapped_column(default=False, init=False)
failure_modes: Mapped[list["FailureMode"]] = relationship(
    default_factory=list, back_populates="tests"
)

idx: Mapped[int] = mapped_column(
    primary_key=True, autoincrement=True, init=False, sort_order=-1
)

@validates("failure_modes")
def validate_failure_modes(self, key, failure_mode):
    """
    Validator for failure modes. When attribute is changed, updates passed to be false if there are any fails.
    """
    self.count += 1
    currently_passes = all([fm.passed for fm in self.failure_modes])
    self.passed = currently_passes and failure_mode.passed
    return failure_mode

@__reg.mapped_as_dataclass 类失败模式: 表名 =“failure_mode”

passed: bool = mapped_column()
tests: Mapped["DeviceTestResult"] = relationship(
    back_populates="failure_modes", default=None
)

idx: Mapped[int] = mapped_column(
    primary_key=True, autoincrement=True, init=False, sort_order=-1
)
test_idx: Mapped[int] = mapped_column(ForeignKey("device_test.idx"), init=False)

当将列表分配给 DeviceTestResult.failure_modes 时,我期望发生的情况是:

An individual FailureMode is validated by validate_failure_mode
The FailureMode is added to DeviceTestResult.failure_modes

发生的情况是验证每个单独的 FailureMode,然后完成分配。

为了解决我的问题,我使用

hybrid_properties
将 DeviceTestResult.passed 更改为只读属性,直接读取 DeviceTestResult.failure_modes 的值。

© www.soinside.com 2019 - 2024. All rights reserved.