在Django中保存模型时出现“警告:字段'id'没有默认值”

6 投票
8 回答
12921 浏览
提问于 2025-04-17 06:00

我在Django中有一个非常基础的模型:

class Case(models.Model):
    name = models.CharField(max_length=255)
    created_at = models.DateTimeField(default=datetime.now)
    updated_at = models.DateTimeField(default=datetime.now)

    def save(self):
        if self.created_at == None:
             self.created_at = datetime.now()
        self.updated_at = datetime.now()
        super(Case, self).save()

    class Meta:
        db_table = u'cases'

因为我没有指定主键(PK),所以Django自动帮我处理了这个问题。我在数据库中看到一个叫“id”的字段,它被标记为主键,并且是自动递增的。我觉得收到这个警告有点奇怪,因为在数据库和模型方面一切正常。错误信息是:

_mysql_exceptions.Warning

Warning: Field 'id' doesn't have a default value

我解决这个问题的方法是在保存时把id设置为0。这样可以消除警告,而且id会被正确设置,因为MySQL会处理这个问题。

case = Case()
case.id = 0 #ugly workaround for - Warning: Field 'id' doesn't have a default value
case.name = request.POST[u'case[name]']
case.save()

不过这个解决方案有以下几个问题:

  1. 看起来不太好
  2. 保存后新的主键无法访问,这让序列化变得不可能

有没有人知道怎么解决这个问题?

我正在运行:

Python 2.7.2
django.VERSION (1, 3, 1, 'final', 0)
mysql  Ver 14.14 Distrib 5.1.45, for apple-darwin10.2.0 (i386) using readline 5.1
MySQL_python-1.2.3-py2.7-macosx-10.4-x86_64.egg

我的创建表的代码看起来是这样的:

CREATE TABLE `cases` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=45 DEFAULT CHARSET=latin1

8 个回答

2

你的保存方法其实没必要,你可以使用这两个参数:DateField.auto_nowDateField.auto_now_add。这两个参数可以自动处理你的创建时间和更新时间:

  1. DateField.auto_now:每次保存对象时,自动把这个字段设置为当前时间。适合用来记录“最后修改”的时间。
  2. DateField.auto_now_add:在对象第一次创建时,自动把这个字段设置为当前时间。适合用来记录创建时间。

试着直接使用默认的保存方法,希望这对你有帮助!

关于 auto_nowauto_now_add 的更多信息,可以查看这里:https://docs.djangoproject.com/en/dev/ref/models/fields/#datefield

5

你有没有机会重新创建一下数据库?看起来可能有些问题。

顺便提一下:如果你已经把 created_at 字段的默认值设置为 datetime.now,那么就不需要再调用 datetime.now() 了。

15

我想对这个问题做一些扩展,因为我这周也遇到了类似的情况。我遇到了同样的错误,查看模型定义和SQL定义后发现:

  1. 受影响的模型要么没有明确定义主键(PK),要么明确定义了主键(这两种情况都有问题)。这看起来似乎没有关系。

  2. 受影响的表的“id”定义和原问题中的一样,也就是 id int(11) NOT NULL AUTO_INCREMENT。主键的设置是正常的。

  3. 查看MySQL的查询日志,我得到了类似这样的信息:

    INSERT INTO `x` (...) VALUES (...)
    SHOW WARNINGS
    ROLLBACK
    

    单独运行这个查询是成功的,SHOW WARNINGS 显示了原问题中提到的警告。

不过,我发现了一个MySQL的解决办法,http://webit.ca/2012/01/field-id-doesnt-have-a-default-value/提到重置id的定义(乍一看似乎没有任何不同)可以解决这个问题。我无法解释为什么这样有效,但它在不需要额外代码修改的情况下解决了问题。我觉得这可能和删除记录有某种联系,但整个问题对我来说似乎没有道理。

撰写回答