【问题标题】:Django 1.7.1 requires a Default value for field - but no entry is in database. Why?Django 1.7.1 需要字段的默认值 - 但数据库中没有条目。为什么?
【发布时间】:2014-11-18 07:09:40
【问题描述】:

我遇到了一个奇怪的问题。我在 Mac OS X Yosemite 上使用 Django 1.7.1,并配置了本地 MySQL 数据库。

通常,我创建一个模型,如果我想添加另一个字段,我只需执行 ./manage.py migrate 并且 Django 会创建一个新的数据库列。

我就是这么做的。这是我的模型:

from django.db import models
from django.utils.translation import ugettext as _


class Product(models.Model):
    CATEGORY_CHOICES = (
        ('apphosting', _('Application Hosting')),
        ('webhosting', _('Web Hosting'))
    )

    category = models.CharField(max_length=25, choices=CATEGORY_CHOICES)
    name = models.CharField(max_length=25)
    price_monthly = models.FloatField()

    def __unicode__(self):
        return self.name

请注意,我已添加字段price_monthly。然后,我做了一个./manage.py migrate

(mysphere)dmanser@ragamuffin:~/git/mysphere on master [!?]$ ./manage.py migrate
Operations to perform:
  Synchronize unmigrated apps: crispy_forms
  Apply all migrations: customers, sessions, admin, sites, flatpages, contenttypes, products, auth
Synchronizing apps without migrations:
  Creating tables...
  Installing custom SQL...
  Installing indexes...
Running migrations:
  No migrations to apply.
  Your models have changes that are not yet reflected in a migration, and so won't be applied.
  Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.

好吧,我做了一个./manage.py makemigrations,结果是:

(mysphere)dmanser@ragamuffin:~/git/mysphere on master [!?]$ ./manage.py makemigrations
You are trying to add a non-nullable field 'price_monthly' to product without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows)
 2) Quit, and let me add a default in models.py
Select an option:

这里奇怪的是,这个模型还没有条目。那么,如果数据库中没有产品,我为什么需要提供默认值呢?

我开始拔头发,昨天我尝试了几件事。 3小时后,我放弃了。

【问题讨论】:

    标签: python django django-migrations


    【解决方案1】:

    迁移系统的设计使得单个迁移可以应用于多个数据库。例如,您可以有一个开发版本、一个暂存版本和一个或多个生产版本。这就是为什么进行迁移与应用迁移是一个不同的步骤,以及为什么makemgirations 不能只查看当前活动的数据库来发现它没有有任何行。如果您随后尝试将迁移应用到执行此操作的数据库,该怎么办?

    您的解决方案很简单:因为没有行,所以选项 1(在所有现有行上设置默认值)根本不会做任何事情。所以选择选项 1,以及你喜欢的任何值。

    【讨论】:

    • 嗨凯文谢谢你的解释。我明白你的意思,但是在另外两个 Django 项目中,我可以做到这一点,而无需提供默认值。我仍然认为我的迁移有问题。
    • @Daniel:我无法与您的其他项目交谈(也许您的领域有 null=True?也许您在第一次运行 migrate 之前进行了更改?),但是您的在这里重新描述正是应该发生的事情。一切正常,解决方案很简单,因此无需拔掉头发。 ;-)
    • 谢谢大家。感谢您的帮助。
    【解决方案2】:

    您之前已经应用了迁移,因此表已经创建。现在您要添加一个不能为空但尚未定义默认值的列。

    由于迁移将向现有表添加列,因此它需要足够的数据,以便您的迁移不会违反架构;因此提示。

    如果您要删除表,然后运行迁移,您将不会遇到此错误。但是,由于初始迁移已经创建了表,因此任何未来的迁移都不能违反其引用完整性。

    【讨论】:

      【解决方案3】:

      我遇到过很多次了,假设你的项目 myproject 中有一个名为 app1 的应用,在这种情况下你能做的最好的事情就是去删除 app1/migrations 然后再试一次它应该可以正常工作

      【讨论】:

        猜你喜欢
        • 2012-08-04
        • 1970-01-01
        • 2015-05-18
        • 1970-01-01
        • 2014-02-25
        • 1970-01-01
        • 2020-03-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多