Django/Python 不支持 FloatField 的 None 值

2 投票
2 回答
5250 浏览
提问于 2025-04-16 14:40

我在Django里有一个叫做Account的类,它里面有一个属性叫interest_rate(这个对应数据库里的account.interest_rate)。这是interest_rate

interest_rate = models.FloatField(null=True, blank=True)

如果我这样做,它是可以工作的:

account = Account()
account.interest_rate = 5
account.save()

但是如果我这样做,就不行了:

account = Account()
account.interest_rate = None
account.save()

我收到了这个错误:

Traceback (most recent call last):
  File "./import.py", line 18, in <module>
    cProfile.run('g.process()', 'prof')
  File "/usr/lib/python2.6/cProfile.py", line 29, in run
    prof = prof.run(statement)
  File "/usr/lib/python2.6/cProfile.py", line 135, in run
    return self.runctx(cmd, dict, dict)
  File "/usr/lib/python2.6/cProfile.py", line 140, in runctx
    exec cmd in globals, locals
  File "<string>", line 1, in <module>
  File "/home/jason/projects/mcifdjango/mcif/models/generic_import.py", line 34, in process
    Account.save_in_bulk(self.rows)
  File "/home/jason/projects/mcifdjango/mcif/models/account.py", line 45, in save_in_bulk
    cursor.execute(Account.bulk_insert_statement(rows))
  File "/usr/lib/pymodules/python2.6/django/db/backends/util.py", line 15, in execute
    return self.cursor.execute(sql, params)
  File "/usr/lib/pymodules/python2.6/django/db/backends/mysql/base.py", line 86, in execute
    return self.cursor.execute(query, args)
  File "/usr/lib/pymodules/python2.6/MySQLdb/cursors.py", line 168, in execute
    if not self._defer_warnings: self._warning_check()
  File "/usr/lib/pymodules/python2.6/MySQLdb/cursors.py", line 82, in _warning_check
    warn(w[-1], self.Warning, 3)
_mysql_exceptions.Warning: Data truncated for column 'interest_rate' at row 1

为什么我不能在一个可以为空的字段上保存空值呢?我是不是做错了什么?

2 个回答

6

在mysql中,这个字段可以为空吗?

我之前遇到过这样的错误:我创建了一个模型,里面有一个字段最开始是不允许为空的,后来在创建表的时候又改成可以为空。因为mysql在最开始创建表的时候就设置了这个字段不能为null,所以即使django允许插入,也会失败。

要解决这个问题,我会先检查一下mysql中的表定义。如果这个字段是null=false,你可以手动修改它,或者如果你不在乎数据,可以删除这个表,然后重新运行./manage.py syncdb来重新创建表。

如果你使用south来管理你的数据库迁移,可以创建一个新的迁移,然后运行它。

如果mysql表的实例没有显示null=false,那就可能是其他问题。

更新:我们发现mysql中的列是可以为空的,所以我在更新这个回答。

我使用的是Django 1.2.5,你用的是什么版本?

我在我的系统中创建了这个模型。

from django.db import models

#================================================================================
class Account(models.Model):
    interest_rate = models.FloatField(null=True, blank=True)

然后通过shell运行它,对我来说是成功的。

Python 2.6.6 (r266:84292, Sep  8 2010, 16:19:33) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from aggra.models import Account
>>> account = Account()
>>> account.interest_rate = None
>>> account.save()
>>> exit()

这是我在django中的创建语句。aggra是我的应用名称。

$ python manage.py sql aggra
BEGIN;
CREATE TABLE `aggra_account` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `interest_rate` double precision
)
;
COMMIT;

这是我在mysql中看到的表的样子。

CREATE TABLE `aggra_account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `interest_rate` double DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

这看起来和你的一样吗?

更新 2 我们发现它看起来是一样的,并且使用的django和python版本大致相同。

你的mysql版本是什么?

你的SQL模式是什么?我的是空的。

mysql> show variables where Variable_name = 'sql_mode';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_mode      |       |
+---------------+-------+
1 row in set (0.00 sec)

如果你设置为严格模式,那么你需要改成宽松一些的模式。

http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html

可以参考一下。

http://forums.mysql.com/read.php?11,132672,132693#msg-132693

1

我之前在写SQL查询的时候搞错了,把空字符串放在了应该放NULL的地方。我把这个问题修正了,现在一切正常。

我写的查询大概是这样的:

INSERT INTO account (interest_rate) values ('')

但其实应该是这样的:

INSERT INTO account (interest_rate) values (NULL)

这两种写法在MySQL里都能正常工作,但在Python/Django里,前一种写法就不行。

撰写回答