【问题标题】:Saving a model in Django gives me "Warning: Field 'id' doesn't have a default value"在 Django 中保存模型给了我“警告:字段 'id' 没有默认值”
【发布时间】:2011-11-10 00:46:38
【问题描述】:

我在 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. 保存后新的 PK 无法访问,这使得它 无法正确序列化

有谁知道如何解决这个问题?

我在跑步:

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

【问题讨论】:

  • 您使用的是什么版本? Python、django、mysql、mysql驱动?另外,你能把mysql“show create table yourappname_cases;”的结果贴出来吗?
  • 好主意。添加到问题的详细信息

标签: python mysql django


【解决方案1】:

本周我遇到了这个问题,我想详细说明一下。我遇到了同样的错误,查看模型定义和 SQL 定义表明:

  1. 受影响的模型要么没有明确定义 PK,要么明确定义了 PK(两者都有问题)。仅此一项似乎无关紧要。

  2. 受影响的表具有 OP 中的“id”定义,即id int(11) NOT NULL AUTO_INCREMENTPRIMARY KEY 按预期设置。

  3. 查看 MySQL 查询日志,我得到了这样的结果:

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

    单独运行查询成功,SHOW WARNINGS 反映了 OP 中记录的警告。

然而,我遇到了一个 MySQL 端修复,http://webit.ca/2012/01/field-id-doesnt-have-a-default-value/ 提到重置 id 定义(粗略一看似乎没有任何不同)解决了这个问题。我无法解释为什么会这样,但它解决了这个问题而无需任何额外的代码更改。我相信这可能在某种程度上与删除记录有关,但整个问题对我来说似乎毫无意义。

【讨论】:

  • +1 谢谢,就像 OP 我想知道 mysql 中的表 def 是否正确,为什么会出现错误,但这澄清了,mysql 中的一个错误有任何一个提交的票吗?
  • 在使用 MySQL 将列迁移到 Autofield 后,我在使用 Django/South 时遇到了这个问题。显然,此警告是迁移的副作用,您建议的 MySQL 端修复解决了该问题。这里有一张南票了解更多信息:south.aeracode.org/ticket/1160
  • 以防万一链接断开,这是在您遇到问题的表上运行的命令:ALTER TABLE problem_table MODIFY `id` INT(11) NOT NULL AUTO_INCREMENT;
【解决方案2】:

您有机会重新创建数据库吗?好像有什么问题。

附带说明:如果您已经将字段的默认设置为datetime.now,则不必为created_at 调用datetime.now()

【讨论】:

  • 我的数据库有什么问题? PK 上的属性看起来与 Django 生成表的 PK 上的属性完全相同
【解决方案3】:

你的save方法真的没必要,你可以使用参数:DateField.auto_nowDateField.auto_now_add。这些参数处理您的 created_at 和 updated_at 属性:

  1. DateField.auto_now:每次保存对象时自动将字段设置为现在。对于“最后修改”时间戳很有用。
  2. DateField.auto_now_add:首次创建对象时自动将字段设置为现在。用于创建时间戳。

使用默认的 save() 方法再试一次,希望对您有所帮助!

有关auto_nowauto_now_add 的更多信息请参见:https://docs.djangoproject.com/en/dev/ref/models/fields/#datefield

【讨论】:

  • 好的,所以错误肯定不在save() 方法中。一定是数据库有问题。你用的是 South 还是类似的东西?
  • 是的,我使用的是 South,但是数据库看起来很好,模型定义也很好。它们之间唯一的东西是 Python mysql 驱动程序,对吗?那就是我看到警告被抛出的地方
  • 我在使用 South 应用时有很多不好的经历,我敢打赌这与它有关。有时删除表很有用,使用manage.py sqlall [appname] SQL 生成的代码自己创建它并运行假迁移migrate [appname] [number_of_change] --fake
  • 好的,我试一试。我是否必须告诉所有其他开发人员也这样做?你对管理迁移有什么建议吗?对不起,我在 Django 上的第 3 天,我错过了一些 Rails 功能......比如迁移......
  • 好吧,真的不建议这样做。我建议是因为它对我有用好几次,但如果你在 Django 或 South 方面没有太多经验,这可能不是最好的选择。这里有一个重要的问题:这个数据库曾经工作过吗?我的意思是,在出错之前它工作正常吗?
【解决方案4】:

save 方法有时会使用附加参数和关键字参数,但您不处理它们。 我不确定,但这可能会解决您的问题

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

【讨论】:

    【解决方案5】:

    我确定你现在可能已经解决了这个问题,但我刚刚遇到了同样的问题。

    原来没有为主键设置自动增量,所以我通过为我的数据库中的每个主键打开自动增量来解决这个问题。

    希望对遇到同样问题的其他人有所帮助。

    【讨论】:

      【解决方案6】:

      我通过过滤掉警告来解决这个问题:

      import warnings
      warnings.filterwarnings("ignore", "Field 'id' doesn't have a default value")
      

      现在保存和序列化看起来不错

      【讨论】:

      • 似乎不是正确的解决方案。没有其他人收到该警告。
      • 这是一个非常绝望的解决方案
      • 这是错的,看@Aea的回答,好像是mysql端的问题
      • 这不是解决方案,您只是忽略了警告消息
      【解决方案7】:

      我也有同样的问题,当我查看 mysql 结构时,字段“id”不是第一个字段。我改变了结构,使它作为第一个字段出现,然后我的问题就解决了。但我仍然不知道它背后的真正问题。

      为该表解决问题之前的 SQL 脚本: 如果不存在则创建表 marketing_sponseredhashtag ( user_id int(11) 非空, start_date 日期时间不为空, created datetime NOT NULL DEFAULT '2013-02-12 14:00:04', modified datetime NOT NULL DEFAULT '2013-02-12 14:00:04', payment十进制(10,2)不为空, paid tinyint(1) NOT NULL DEFAULT '0', status tinyint(1) NOT NULL DEFAULT '0', expiry_date 日期时间不为空, id int(11) NOT NULL AUTO_INCREMENT, tag varchar(180) 非空, 主键 (id), 键marketing_sponseredhashtag_403f60f (user_id) ) ENGINE=MyISAM 默认字符集=latin1 AUTO_INCREMENT=4 ;

      问题修复后的结构: 如果不存在则创建表 marketing_sponseredhashtag ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) 非空, start_date 日期时间不为空, created datetime NOT NULL DEFAULT '2013-02-12 14:00:04', modified datetime NOT NULL DEFAULT '2013-02-12 14:00:04', payment十进制(10,2)不为空, paid tinyint(1) NOT NULL DEFAULT '0', status tinyint(1) NOT NULL DEFAULT '0', expiry_date 日期时间不为空, tag varchar(180) 非空, 主键 (id), 键marketing_sponseredhashtag_403f60f (user_id) ) ENGINE=MyISAM 默认字符集=latin1 AUTO_INCREMENT=4 ;

      【讨论】:

        【解决方案8】:

        我在运行迁移时遇到了同样的错误,结果我不得不更改默认 django 表的结构:django_admin_logdjango_content_typedjango_migrations 因为主键设置不正确(我不知道为什么,可能在某些时候迁移不好)

        我使用以下查询来更新表格:

        ALTER TABLE django_migrations MODIFY id INT(11) NOT NULL AUTO_INCREMENT;
        

        【讨论】:

          猜你喜欢
          • 2011-06-02
          • 1970-01-01
          • 1970-01-01
          • 2014-11-09
          • 1970-01-01
          • 2010-10-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多