如何编写验证器检查记录是否仅含一个值为1的字段及单动作验证实现问询
解决多字段单值验证器问题
嘿,我来帮你搞定这两个验证器的问题!
1. 编写验证器检查多个字段仅有一个整数值为1
核心思路是收集目标字段的值,统计其中等于1的数量必须严格等于1。结合SQLModel(基于Pydantic)的验证机制,推荐用root_validator实现——它能在所有字段验证完成后对整个模型数据做检查,避免逐个字段验证时的数据不全问题。
示例代码:
from sqlmodel import SQLModel, Field, root_validator class ActionRecord(SQLModel): field1: int = Field(default=0) field2: int = Field(default=0) field3: int = Field(default=0) # 其他需要检查的字段... @root_validator(skip_on_failure=True) def exactly_one_field_is_one(cls, values): # 定义需要检查的目标字段列表 target_fields = ["field1", "field2", "field3"] # 统计值为1的字段数量 count_ones = sum(1 for field in target_fields if values.get(field) == 1) if count_ones != 1: raise ValueError("Exactly one of the target fields must be set to 1") return values
2. 修正你的MouseAction验证器问题
你当前的代码有两个关键问题:
sum(values)逻辑错误:在字段级@validator逐个验证时,values只包含已经验证过的字段(比如验证blur时,只有user_id和blur在values里),此时求和会得到错误结果。- 返回值错误:字段级验证器应该返回当前字段的原始值
v,而不是values字典。
正确的做法是使用root_validator,在所有字段验证完成后检查动作字段的总和:
from sqlmodel import SQLModel, Field, root_validator class MouseAction(SQLModel): user_id: int = Field(foreign_key="user.id") # 注意foreign_key参数要传字符串形式的表名+字段 blur: int = Field(default=0) focus: int = Field(default=0) copy_: int = Field(alias='copy', default=0) paste: int = Field(default=0) left_click: int = Field(default=0) right_click: int = Field(default=0) double_click: int = Field(default=0) @root_validator(skip_on_failure=True) def check_single_action(cls, values): # 收集所有动作字段的值 action_values = [ values["blur"], values["focus"], values["copy_"], values["paste"], values["left_click"], values["right_click"], values["double_click"] ] total_actions = sum(action_values) if total_actions > 1: raise ValueError('Only a single action is allowed per record') elif total_actions < 1: raise ValueError('Record must have an action/event') return values
补充说明:
skip_on_failure=True表示如果前面的字段验证失败,就跳过这个根验证器,避免抛出无关的错误。- 直接从
values中取出所有动作字段的值求和,确保统计的是完整的所有字段数据,能准确判断是否有且仅有一个动作被设置为1(假设你的动作字段仅取值0或1)。
内容的提问来源于stack exchange,提问作者HALLOWEEN
相关产品推荐
相关产品推荐

