使用
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
描述符和混合,但还没有成功。
问题不在于验证器没有在列表中的每个项目上运行(它是)——它与验证完成的顺序有关。
为了提供一些上下文,我有一个 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 的值。