在Django CharFields中自动截断max_length处的字段

时间:2010-08-11 15:10:19

标签: django postgresql django-models

我的字段设置为max_length。当我保存模型实例,并且字段的值大于max_length时,Django在数据库级别强制执行max_length。 (参见关于模型的Django文档:http://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.CharField.max_length

但是,由于我使用Postgres,我收到DatabaseError这样的例外:

DatabaseError: value too long for type character varying(1000)

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

我应该只编写一个从models.Model导入的自定义类并覆盖save()方法,循环遍历每个_meta.field,检查max_length,然后截断?这似乎不够优雅,必须有更好的方法。

4 个答案:

答案 0 :(得分:37)

你可以创建一个自动截断字段的自定义字段(我认为这段代码应该有效,但仔细检查一下):

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.CharField文件中使用models.py,而只需使用TruncatingCharField。

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

答案 1 :(得分:5)

为什么不使用TextField?从手册:

  

对于大量文字,请使用   TextField更新。

答案 2 :(得分:3)

为什么不使用ModelForm。 ModelForm强制执行验证,将其默认max_length设置为模型字段的max_length属性,并在调用form.is_valid()时引发正确的验证错误。这样您就不必保存表单,直到表单被验证为止。

或者,如果你想默默地传递验证和截断最适合你,写一个简单的django表单,并编写一个clean方法,将输入字符串截断为max_length并返回剥离的数据。在验证表单后从form.cleaned_data获取数据并保存对象。

所有考虑到这一事实,Forms都是为了在进入DB之前验证数据而设计的。

答案 3 :(得分:-3)

这似乎不够优雅,必须有更好的方法。

首先发生截断行为的唯一原因是MySQL无法遵守SQL标准。在尝试将字符串插入到不足以容纳它的VARCHAR字段时,抛出异常是正确的响应。 MySQL会截断并插入。

如果你想要无声地破坏你的数据,那么你必须以某种方式手动完成它 - PostgreSQL永远不会为你做这件事。