关于postgresql:在Django CharFields中自动截断max_length处的字段

Auto-truncating fields at max_length in Django CharFields

我有一个字段有一个max_length集。当我保存一个模型实例,并且该字段的值大于max_length时,django在数据库级别强制执行max_length。(参见django docs on models:http://docs.djangoproject.com/en/dev/ref/models/fields/django.db.models.charfield.max_length)

但是,由于我使用的是Postgres,因此我收到一个DatabaseError例外,如下所示:

1
DatabaseError: VALUE too long FOR TYPE CHARACTER VARYING(1000)

我更喜欢自动截断值(所以我没有例外)。现在,我可以手动执行此操作,但我真正想要的是让所有模型自动截断值。(不一定聪明。只需在第99个字符处切断它就可以了。)

我应该编写一个从models.model导入的自定义类并重写save()方法,循环遍历每个meta.field,检查最大长度,然后截断吗?这看起来不雅,肯定有更好的方法。


您可以创建一个自动截断字段的自定义字段(我认为这段代码可以工作,但要仔细检查它):

1
2
3
4
5
6
class TruncatingCharField(models.CharField):
    def get_prep_value(SELF, VALUE):
        VALUE = super(TruncatingCharField,SELF).get_prep_value(VALUE)
        IF VALUE:
            RETURN VALUE[:SELF.max_length]
        RETURN VALUE

然后,不要在您的models.py文件中使用models.CharField,而是使用trunctingcharfield。

get_prep_value为在数据库中插入的字段准备了值,因此它是理想的截断位置。


为什么不使用文本字段?从手册中:

For large amounts of text, use
TextField.


为什么不使用ModelForm。ModelForm强制进行验证,将其默认最大长度设置为模型字段的最大长度属性,并在调用form.is_valid()时引发正确的验证错误。这样,在验证表单之前,您不必保存表单。

或者,如果您希望以静默方式通过验证并截断最适合您的值,那么可以编写一个简单的django表单,然后编写一个干净的方法,将输入字符串截断到最大长度并返回剥离的数据。表单验证后,从form.cleaned_data获取数据,保存对象。

考虑到这一事实,表单设计用于在进入数据库之前验证数据。


这看起来不雅,肯定有更好的方法。

截断行为首先发生的唯一原因是MySQL未能遵守SQL标准。当试图将一个字符串插入一个不足以容纳它的varchar字段时,引发异常是正确的响应。MySQL会截短并插入。

如果你想悄悄地破坏你的数据,那么你必须以某种方式手动操作——PostgreSQL永远不会为你做这件事。