对于类型字符变化,/ post / 113 /的DatabaseError值太长(10)

时间:2012-12-06 02:34:48

标签: django postgresql heroku

我在Heroku上使用postgresql作为我的Django App。当我尝试对我的帖子发表评论时,我有时会得到这个错误(有时候不是所有的时间)。

尽管有错误,评论仍然保存,但save()后面的所有代码都没有执行。

此问题仅发生在postgresql上。在我使用sqlite的本地主机上,一切正常。

我不确定这是什么原因。

这就是我的模型的样子

class Comment(models.Model):
    post = models.ForeignKey(post)
    date = models.DateTimeField(auto_now_add=True)
    comment = models.TextField()
    comment_user = models.ForeignKey(User)

这就是我的评论模型的样子。 那是因为我没有添加max_length进行评论吗? 这是Traceback

DatabaseError at /post/114/
value too long for type character varying(10)
Request Method: POST
Request URL:    http://www.mysite.com/post/114/
Django Version: 1.4.1
Exception Type: DatabaseError
Exception Value:    
value too long for type character varying(10)
Exception Location: /app/.heroku/venv/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py in execute, line 52
Python Executable:  /app/.heroku/venv/bin/python2.7
Python Version: 2.7.2
Python Path:    
['/app',
 '/app/.heroku/venv/bin',
 '/app/.heroku/venv/lib/python2.7/site-packages/pip-1.1-py2.7.egg',
 '/app/.heroku/venv/lib/python2.7/site-packages/distribute-0.6.31-py2.7.egg',
 '/app',
 '/app/.heroku/venv/lib/python27.zip',
 '/app/.heroku/venv/lib/python2.7',
 '/app/.heroku/venv/lib/python2.7/plat-linux2',
 '/app/.heroku/venv/lib/python2.7/lib-tk',
 '/app/.heroku/venv/lib/python2.7/lib-old',
 '/app/.heroku/venv/lib/python2.7/lib-dynload',
 '/usr/local/lib/python2.7',
 '/usr/local/lib/python2.7/plat-linux2',
 '/usr/local/lib/python2.7/lib-tk',
 '/app/.heroku/venv/lib/python2.7/site-packages',
 '/app/.heroku/venv/lib/python2.7/site-packages/PIL']
Server time:    Wed, 5 Dec 2012 20:41:39 -0600

2 个答案:

答案 0 :(得分:5)

我无法帮助你处理Django部分(抱歉),所以我只会说PostgreSQL。

在您的应用程序的某个位置,您有一个varchar(10)列,并且您正在尝试将超过10个字符的内容放入其中,您可能在某个地方缺少验证。 SQLite忽略varchar(n)列中的大小,并将其视为text,没有大小限制;所以你可以用SQLite做这样的事情:

sqlite> create table t (s varchar(5));
sqlite> insert into t (s) values ('Where is pancakes house?');
sqlite> select * from t;
s
where is pancakes house?
没有投诉。同样,SQLite允许您执行一些荒谬的操作,例如将字符串放入数字列。

这是你需要做的:

  1. 当您在PostgreSQL上部署时,停止在SQLite上进行开发。在本地安装PostgreSQL并在此基础上进行开发,你甚至应该安装你将在Heroku使用的相同版本的PostgreSQL。数据库之间存在各种差异会让您头疼,这个小字段大小问题只是您对跨数据库问题的温和介绍。
  2. 停止使用varchar(n)和PostgreSQL,只需使用text。在PostgreSQL中使用大小有限的字符串列是没有意义的,除非您有必须限制大小的硬性要求。来自fine manual

      

    短字符串(最多126个字节)的存储要求是1个字节加上实际字符串,其中包括字符空格填充。较长的字符串有4个字节的开销而不是1.长字符串由系统自动压缩,因此磁盘上的物理要求可能更少。 [...]如果您希望存储没有特定上限的长字符串,请使用text ...

         
        

    提示:这三种类型之间没有性能差异,除了使用空白填充类型时存储空间增加,还有一些额外的CPU周期来检查存储长度时的长度 - 受限制的列。虽然character(n)在其他一些数据库系统中具有性能优势,但PostgreSQL中没有这样的优势;实际上character(n)通常是三者中最慢的,因为它增加了存储成本。在大多数情况下,应该使用textcharacter varying

      

    因此,除非必须,否则不要使用PostgreSQL中的传统charvarchar,只需使用text

  3. 开始验证您的传入数据,以确保它不会违反您的任何大小或格式限制。
  4. 您可以立即将列从varchar(n)切换到text,并在启动PostgreSQL的同时继续使用SQLite;对于无限长度的字符串,这两个数据库都会对text感到满意,这个简单的修复程序将帮助您解决当前的问题。然后,尽快将开发环境切换到PostgreSQL,以便在代码生成之前捕获这样的问题。

答案 1 :(得分:1)

原因是PostgreSQL实际上根据字段的大小检查数据的长度,如果太大则错误输出,而SQLite完全忽略指定的字段大小,而MySQL默默地截断数据,无法挽救它。让场地变大。