Tortoise ORM无blank=False配置,如何禁止存储空字符串
问题根因
Tortoise ORM 中字段的null=False配置仅限制字段不能存储None值,空字符串''属于合法的字符串类型值,默认不会被拦截。这和Django中null控制数据库层面非空、blank控制业务层面不允许空值的分工逻辑不同,Tortoise本身没有内置blank校验参数,需要自行补充校验逻辑。
解决方案
建议同时在Pydantic序列化层和ORM层配置校验,前者拦截接口层的非法输入,后者作为兜底避免绕过接口直接操作ORM时写入脏数据。
1. ORM模型层面加校验
Tortoise 支持重写模型的clean()方法自定义校验规则,调用create()、save()方法时会自动触发该校验:
from tortoise.exceptions import ValidationError from tortoise.models import Model from tortoise import fields class User(Model): id = fields.IntField(pk=True) email = fields.CharField(100, unique=True, index=True) password = fields.CharField(128) name = fields.CharField(50) surname = fields.CharField(50) def clean(self): # 校验指定字符串字段不可为空或纯空白 str_fields = ["email", "password", "name", "surname"] for field_name in str_fields: value = getattr(self, field_name) if isinstance(value, str) and value.strip() == "": raise ValidationError(f"{field_name} 字段不能是空字符串或纯空白字符")
如果多个模型都需要类似校验,可以把clean()逻辑封装到自定义BaseModel基类中,所有业务模型继承该基类即可。
2. Pydantic Schema层面加校验
在序列化层直接加字段约束,提前拦截非法参数,这里以Pydantic v2为例:
from pydantic import BaseModel, Field, field_validator class UserCreateSchema(BaseModel): email: str = Field(min_length=1, max_length=100) password: str = Field(min_length=1, max_length=128) name: str = Field(min_length=1, max_length=50) surname: str = Field(min_length=1, max_length=50) # 额外校验不能是纯空白字符 @field_validator("email", "name", "surname", "password") @classmethod def check_not_blank(cls, value: str) -> str: if value.strip() == "": raise ValueError("字段不能为空白字符串") return value
3. 自定义全局字段类型(可选)
如果项目大量场景需要禁止空字符串的CharField,可以自定义字段类型实现一劳永逸:
from tortoise import fields from tortoise.exceptions import ValidationError class NonBlankCharField(fields.CharField): def validate(self, value, model_instance): super().validate(value, model_instance) if isinstance(value, str) and value.strip() == "": raise ValidationError(f"{self.model_field_name} 字段不能是空字符串")
业务模型直接替换原生CharField即可:
class User(Model): id = fields.IntField(pk=True) email = NonBlankCharField(100, unique=True, index=True) password = NonBlankCharField(128) name = NonBlankCharField(50) surname = NonBlankCharField(50)
内容的提问来源于stack exchange,提问作者Hahan't
相关产品推荐
相关产品推荐

