Django CharFields中的最大长度自动截断字段

37

我有一个设置了 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个回答

54

你可以创建一个自定义字段来自动截断字段(我认为这段代码应该有效,但请再次确认):

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可以替换为TruncatingCharField

get_prep_value方法用于准备字段值以在数据库中进行插入,因此它是截断字符串的理想位置。


运行得非常顺畅! - Gabe Brown
放在哪里? - Danil
1
我已经很高兴地使用这个程序超过2年了,只有一件事需要强调:在使用.create(或导致创建的变体,如get_or_create)之后,内存实例不会被截断。记住这一点是很好的! refresh_from_db可以正确地显示它被截断了,但是在创建对象后立即刷新对象并不是很好。 - Filipe Pina
我无法找到任何途径从Field类本身控制它,因此我最终在具有TruncatingCharField的模型的save()方法中添加了Field.get_prep_value() - Filipe Pina
在切割值之前,我们应该先去除它的空格(strip())。 - Manoj Jadhav
这很有帮助。我将为那些可能不明显的人添加截断类的使用位。 描述= TruncatingCharField(max_length=1024) - Anjayluh

6
为什么不使用TextField?来自手册的说明如下:
对于大量文本,请使用TextField。

看了你写的内容,如果你想在第999个字符处截断它,那么我认为TextField可能是更好的选择。 - Jordan Reiter
2
好的回答,但可能是针对另一个问题的。 - ibz

3
为什么不使用ModelForm。ModelForm强制进行验证,将其默认max_length设置为模型字段的max_length属性,并在调用form.is_valid()时引发适当的验证错误。这样,您就不必在表单验证之前保存表单。
或者,如果您想要静默通过验证并截断最适合您的内容,请编写一个简单的Django表单,并编写一个清理方法,将输入字符串截断到max_length并返回修剪的数据。在表单经过验证后从form.cleaned_data中取出数据并保存对象。
总体考虑,表单是设计用于在数据进入数据库之前验证数据。

-4

那看起来不太优雅,肯定有更好的方法。

截断行为之所以会发生,仅仅是因为MySQL没有遵守SQL标准。当尝试将字符串插入到一个VARCHAR字段中,而该字段的宽度不足以容纳它时,抛出异常是正确的响应。但MySQL却进行截断并插入。

如果你想悄悄地破坏你的数据,那么你必须手动完成——PostgreSQL永远不会替你这样做。


5
这个问题是关于Django,而不是关于PostgreSQL。我喜欢PostgreSQL遵循标准并引发一个错误的做法,但是我(和楼主一样)希望有一种方法让Django知道可以截断数据(在尝试插入之前)。 - ibz
2
好的,自动执行此操作可能是一个缺陷。但是提供自动执行此操作的选项则是一种功能。 - Tomasz Gandor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接