如何在Cerberus中校验数字长度?ISBN字段需支持10或13位
解决Cerberus中ISBN字段的10/13位数字验证问题
嘿,我之前在Cerberus里处理ISBN验证时也踩过这个坑!你遇到的问题其实是因为Cerberus的maxlength/minlength只对字符串类型生效,数字/整数类型根本不吃这套规则。给你两个实用的解决方案:
方案1:用正则+anyof适配不同类型
如果你的ISBN既可能是字符串格式(比如带引号的数字)也可能是整数,我们可以用anyof分别针对两种类型设置规则:
from cerberus import Validator book_schema = { "isbn": { "anyof": [ # 匹配10或13位的数字字符串 { "type": "string", "regex": r"^\d{10}$|^\d{13}$" }, # 匹配10或13位的整数 { "type": "integer", # 用数值范围锁定位数:10位最小是1000000000,13位最大是9999999999999 "min": 1000000000, "max": 9999999999999, # 再通过anyof区分10位和13位的数值区间 "anyof": [ {"max": 9999999999}, # 10位整数的最大值 {"min": 1000000000000} # 13位整数的最小值 ] } ] } } # 测试验证效果 v = Validator(book_schema) print(v.validate({"isbn": "9781234567890"})) # 13位字符串 → True print(v.validate({"isbn": 1234567890})) # 10位整数 → True print(v.validate({"isbn": "123456789"})) # 9位字符串 → False print(v.validate({"isbn": 123456789})) # 9位整数 → False
方案2:自定义验证规则(更简洁灵活)
如果觉得上面的写法太啰嗦,直接自定义一个验证函数,不管输入是字符串还是数字,统一转成字符串判断长度和是否为纯数字:
from cerberus import Validator # 自定义ISBN验证函数 def check_isbn_valid(field, value, error): isbn_str = str(value) # 检查长度是10或13,且全为数字 if len(isbn_str) not in (10, 13) or not isbn_str.isdigit(): error(field, "ISBN必须是10位或13位的纯数字") # 注册自定义验证器 v = Validator() v.add_validator("isbn_valid", check_isbn_valid) # 编写Schema book_schema = { "isbn": { "type": ["string", "integer"], # 允许字符串或整数类型 "isbn_valid": True # 启用自定义验证规则 } } v.schema = book_schema # 测试验证效果 print(v.validate({"isbn": "9780306406157"})) # 13位字符串 → True print(v.validate({"isbn": 9780306406157})) # 13位整数 → True print(v.validate({"isbn": "abc123456789"})) # 含非数字字符 → False print(v.validate({"isbn": 123456789})) # 9位整数 → False
简单总结一下:Cerberus的maxlength/minlength是字符串专属规则,数字类型得用数值范围或者自定义函数来约束长度。第二种方案更推荐,因为代码更简洁,扩展性也更强(比如后续可以加ISBN的校验位验证)。
内容的提问来源于stack exchange,提问作者Nerldy
相关产品推荐
相关产品推荐

