我最近注意到我在数据库中来自用户的某些条目包含错误编码的字符串,例如ó
当ó
显然意味着时。它来自复制粘贴未正确编码的其他网站,这超出了我的控制范围。我发现我可以添加这个验证器来捕获这种情况并引发异常 - 这是一个附加模型的示例:
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError
import ftfy
def validate_ftfy(value):
value_ftfy = ftfy.ftfy(value)
if value_ftfy != value:
raise ValidationError(
_('Potential UTF-8 encoding error: %(value)r'
' decoded to %(value_ftfy)r.'),
params={'value': value, 'value_ftfy': value_ftfy}
)
class Message(models.Model):
content = models.CharField(max_length=1000, validators=[validate_ftfy])
def save(self, *args, **kwargs):
self.full_clean()
return super(Message, self).save(*args, **kwargs)
问题是,现在我发现了它,我认为在我的任何CharField,TextField等实例中跳过它都没有意义。有没有办法将此验证器插入所有数据类型,以便如果任何非二进制具有无效的 UTF-8,我可以指望它不会进入数据库?
没有钩子可以向内置字段添加额外的验证器,我不确定这是一个好主意,因为它们在 Django 核心的其他地方使用。
我认为对您来说最好的选择是定义一个已经应用验证的自定义字段,并将其用于替代CharField
,例如:
class FtfyCharField(CharField):
default_validators = [validate_ftfy]
class Message(models.Model):
content = FtfyCharField(max_length=1000)
如果你想把它应用到其他类型的领域,你可以把它实现为一个mixin,例如:
class FtfyFieldMixin(models.Field):
default_validators = [validate_ftfy]
class FtfyCharField(models.CharField, FtfyFieldMixin):
pass
class FtfyTextField(models.TextField, FtfyFieldMixin):
pass