0

我最近注意到我在数据库中来自用户的一些条目包含错误编码的字符串,例如明确表示ó什么时候。ó它来自其他未正确编码的网站的复制粘贴,这是我无法控制的。我发现我可以添加此验证器来捕获此类情况并引发异常 - 这是一个带有附加模型的示例:

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,我可以指望它不会进入数据库?

4

1 回答 1

1

没有钩子可以向内置字段添加额外的验证器,我不确定这是一个好主意,因为它们在 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
于 2019-11-26T13:50:30.443 回答