使用south迁移数据库表

时间:2014-04-15 00:19:36

标签: mysql django sqlite django-south

我没有使用南方。现在我想添加几列。我搞砸了吗?

(env)noah:code broinjc$ ./manage.py schemamigration reports --initial
Creating migrations directory at '/Users/broinjc/esp/code/reports/migrations'...
Creating __init__.py in '/Users/broinjc/esp/code/reports/migrations'...
 + Added model reports.Classroom
 + Added model reports.Student
 + Added model reports.SurveySet
 + Added model reports.Survey
Created 0001_initial.py. You can now apply this migration with: ./manage.py migrate reports
(env)noah:code broinjc$ ./manage.py migrate reports
Running migrations for reports:
 - Migrating forwards to 0001_initial.
 > reports:0001_initial
FATAL ERROR - The following SQL query failed: CREATE TABLE "reports_classroom" ("id" integer NOT NULL PRIMARY KEY, "user_id" integer NOT NULL, "added" datetime NOT NULL, "updated" datetime NOT NULL, "name" varchar(30) NOT NULL, "am_or_pm" varchar(2) NOT NULL)
The error was: table "reports_classroom" already exists
 ! Error found during real run of migration! Aborting.

 ! Since you have a database that does not support running
 ! schema-altering statements in transactions, we have had 
 ! to leave it in an interim state between migrations.

! You *might* be able to recover with:   = DROP TABLE "reports_classroom"; []
   = DROP TABLE "reports_student"; []
   = DROP TABLE "reports_surveyset"; []
   = DROP TABLE "reports_survey"; []

 ! The South developers regret this has happened, and would
 ! like to gently persuade you to consider a slightly
 ! easier-to-deal-with DBMS (one that supports DDL transactions)
 ! NOTE: The error which caused the migration to fail is further up.
Error in migration: reports:0001_initial

看到这一切之后,我想,也许我需要更新我的模型(使它们与sqlite db不一致)所以我更新了它们然后运行相同的命令但是使用--auto而不是初始...

(env)noah:code broinjc$ ./manage.py schemamigration reports --auto
 ? The field 'SurveySet.top_num' does not have a default specified, yet is NOT NULL.
 ? Since you are adding this field, you MUST specify a default
 ? value to use for existing rows. Would you like to:
 ?  1. Quit now, and add a default to the field in models.py
 ?  2. Specify a one-off value to use for existing columns now

...所以我继续选择2,然后继续迁移......

(env)noah:code broinjc$ ./manage.py migrate reports
Running migrations for reports:
 - Migrating forwards to 0002_auto__add_field_surveyset_top_num__add_field_surveyset_externalizer_ra.
 > reports:0001_initial

FATAL ERROR - The following SQL query failed: CREATE TABLE "reports_classroom" ("id" integer NOT NULL PRIMARY KEY, "user_id" integer NOT NULL, "added" datetime NOT NULL, "updated" datetime NOT NULL, "name" varchar(30) NOT NULL, "am_or_pm" varchar(2) NOT NULL)
The error was: table "reports_classroom" already exists
 ! Error found during real run of migration! Aborting.


 ! Since you have a database that does not support running
 ! schema-altering statements in transactions, we have had 
 ! to leave it in an interim state between migrations.

! You *might* be able to recover with:   = DROP TABLE "reports_classroom"; []
   = DROP TABLE "reports_student"; []
   = DROP TABLE "reports_surveyset"; []
   = DROP TABLE "reports_survey"; []

1 个答案:

答案 0 :(得分:2)

我会尝试解释发生了什么,以便您更好地了解如何做自己想做的事。

在使用南方之前,您在数据库中有一些表,这些表是在您第一次运行syncdb时从模型生成的。

如果更改模型,假设您添加了一个字段“my_field”,Django在尝试读/写时会失败,因为该表不包含名为“my_field”的列。您通常必须转储整个表并使用syncdb重新创建它。我确定你不想那样做,因为你已经在DB中有了一些数据。

假设您想要在不丢失数据的情况下进行一些更改。首先,您需要"convert" your app to south

基本上,当您运行schemamigration --initial时,South会创建一个脚本(0001_initial.py)来将模型的当前状态复制到数据库中。

如果您通过manage.py migrate reports运行该脚本,它将尝试重新创建您最初拥有的所有表,但在您的情况下,由于您的数据库已经包含这些表,因此它会尖叫您说这些表已存在:

FATAL ERROR - The following SQL query failed: CREATE TABLE "reports_classroom" ("id" integer NOT NULL PRIMARY KEY, "user_id" integer NOT NULL, "added" datetime NOT NULL, "updated" datetime NOT NULL, "name" varchar(30) NOT NULL, "am_or_pm" varchar(2) NOT NULL)
The error was: table "reports_classroom" already exists

让South相信您已经应用了该迁移的方法,您使用--fake选项。

manage.py migrate reports 0001 --fake

这就像说,转到迁移状态0001_initial(您只需要写出名称的数字部分),但实际上不应用更改。

执行此操作后,假设您向其中一个模型添加新字段“my_field_02”。和以前一样,Django引用了模型表中不存在的字段。要在不自己编写SQL的情况下创建它,请执行以下操作:

manage.py schemamigration reports --auto

这会创建一个名为0002_auto__add_my_field_02.py的新迁移,然后您需要通过manage.py migrate reports申请。您也可以说manage.py migrate reports 0002指定要转到的迁移状态,但默认情况下,South会尝试应用以下所有迁移(请记住您已经处于状态0001)。

我强烈建议您在做任何事情之前阅读South's documentation并备份您的生产数据。

tl; dr 阅读this并备份您的数据。