验证
模型验证允许你为模型的每个属性指定格式/内容/继承验证.
验证会自动运行在 create
, update
和 save
上. 你也可以调用 validate()
手动验证一个实例.
属性验证器
你可以自定义验证器或使用由[validator.js][3]实现的几个内置验证器,如下所示.
class ValidateMe extends Model {}
ValidateMe.init({
bar: {
type: Sequelize.STRING,
validate: {
is: ["^[a-z]+$",'i'], // 只允许字母
is: /^[a-z]+$/i, // 与上一个示例相同,使用了真正的正则表达式
not: ["[a-z]",'i'], // 不允许字母
isEmail: true, // 检查邮件格式 (foo@bar.com)
isUrl: true, // 检查连接格式 (http://foo.com)
isIP: true, // 检查 IPv4 (129.89.23.1) 或 IPv6 格式
isIPv4: true, // 检查 IPv4 (129.89.23.1) 格式
isIPv6: true, // 检查 IPv6 格式
isAlpha: true, // 只允许字母
isAlphanumeric: true, // 只允许使用字母数字
isNumeric: true, // 只允许数字
isInt: true, // 检查是否为有效整数
isFloat: true, // 检查是否为有效浮点数
isDecimal: true, // 检查是否为任意数字
isLowercase: true, // 检查是否为小写
isUppercase: true, // 检查是否为大写
notNull: true, // 不允许为空
isNull: true, // 只允许为空
notEmpty: true, // 不允许空字符串
equals: 'specific value', // 只允许一个特定值
contains: 'foo', // 检查是否包含特定的子字符串
notIn: [['foo', 'bar']], // 检查是否值不是其中之一
isIn: [['foo', 'bar']], // 检查是否值是其中之一
notContains: 'bar', // 不允许包含特定的子字符串
len: [2,10], // 只允许长度在2到10之间的值
isUUID: 4, // 只允许uuids
isDate: true, // 只允许日期字符串
isAfter: "2011-11-05", // 只允许在特定日期之后的日期字符串
isBefore: "2011-11-05", // 只允许在特定日期之前的日期字符串
max: 23, // 只允许值 <= 23
min: 23, // 只允许值 >= 23
isCreditCard: true, // 检查有效的信用卡号码
// 自定义验证器的示例:
isEven(value) {
if (parseInt(value) % 2 !== 0) {
throw new Error('Only even values are allowed!');
}
}
isGreaterThanOtherField(value) {
if (parseInt(value) <= parseInt(this.otherField)) {
throw new Error('Bar must be greater than otherField.');
}
}
}
}
}, { sequelize });
请注意,如果需要将多个参数传递给内置的验证函数,则要传递的参数必须位于数组中. 但是,如果要传递单个数组参数,例如isIn
的可接受字符串数组,则将被解释为多个字符串参数,而不是一个数组参数. 要解决这个问题,传递一个单一长度的参数数组,比如[['one','two']]
.
要使用自定义错误消息而不是 [validator.js][3] 提供的错误消息,请使用对象而不是纯值或参数数组,例如不需要参数的验证器可以被给定自定义消息:
isInt: {
msg: "Must be an integer number of pennies"
}
或者如果还需要传递参数,请添加一个 args
属性:
isIn: {
args: [['en', 'zh']],
msg: "Must be English or Chinese"
}
当使用自定义验证器函数时,错误消息将是抛出的 Error
对象所持有的任何消息.
有关内置验证方法的更多详细信息,请参阅 [validator.js project][3] .
提示: 你还可以为日志记录部分定义自定义函数. 只是传递一个方法. 第一个参数将是记录的字符串.
属性验证器 与 allowNull
如果模型的特定字段设置为不允许null(使用allowNull:false
)并且该值已设置为 null
,则将跳过所有验证器并抛出 ValidationError
.
另一方面,如果将其设置为允许null(使用 allowNull:true
)并且该值已设置为 null
,则只会跳过内置验证器,而自定义验证器仍将运行.
例如,这意味着你可以使用一个字符串字段来验证其长度在5到10个字符之间,但也允许 null
(因为当值为 null
时,将自动跳过长度验证器):
class User extends Model {}
User.init({
username: {
type: Sequelize.STRING,
allowNull: true,
validate: {
len: [5, 10]
}
}
}, { sequelize });
你还可以使用自定义验证器有条件地允许 null
值,因为它不会被跳过:
class User extends Model {}
User.init({
age: Sequelize.INTEGER,
name: {
type: Sequelize.STRING,
allowNull: true,
validate: {
customValidator(value) {
if (value === null && this.age !== 10) {
throw new Error("name can't be null unless age is 10");
}
})
}
}
}, { sequelize });
你可以通过设置 notNull
验证器来自定义 allowNull
错误消息:
class User extends Model {}
User.init({
name: {
type: Sequelize.STRING,
allowNull: false,
validate: {
notNull: {
msg: 'Please enter your name'
}
}
}
}, { sequelize });
模型范围验证
验证器也可以在特定字段验证器之后用来定义检查模型.例如,你可以确保纬度
和经度
都不设置,或者两者都设置,如果设置了一个而另一个未设置则验证失败.
模型验证器方法与模型对象的上下文一起调用,如果它们抛出错误,则认为失败,否则通过. 这与自定义字段特定的验证器一样.
所收集的任何错误消息都将与验证结果对象一起放在字段验证错误中,这个错误使用在validate
参数对象中以失败的验证方法的键来命名.即便在任何一个时刻,每个模型验证方法只能有一个错误消息,它会在数组中显示为单个字符串错误,以最大化与字段错误的一致性.
一个例子:
class Pub extends Model {}
Pub.init({
name: { type: Sequelize.STRING },
address: { type: Sequelize.STRING },
latitude: {
type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
validate: { min: -90, max: 90 }
},
longitude: {
type: Sequelize.INTEGER,
allowNull: true,
defaultValue: null,
validate: { min: -180, max: 180 }
},
}, {
validate: {
bothCoordsOrNone() {
if ((this.latitude === null) !== (this.longitude === null)) {
throw new Error('Require either both latitude and longitude or neither')
}
}
},
sequelize,
})
在这种简单情况下,如果给定纬度或经度,而不是同时包含两者,则验证失败. 如果我们尝试构建一个超范围的纬度和经度,那么raging_bullock_arms.validate()
可能会返回
{
'latitude': ['Invalid number: latitude'],
'bothCoordsOrNone': ['Require either both latitude and longitude or neither']
}
这样的验证也可以通过在单个属性上定义的自定义验证器(例如latitude
属性,通过检查(value === null) !== (this.longitude === null)
)来完成, 但模型范围的验证方法更清晰.