添加新的遷移沿着這些線路:
app_name = 'app'
model_name = 'something'
related_model_name = 'something_else'
model_table = '%s_%s' % (app_name, model_name)
pivot_table = '%s_%s_%ss' % (app_name, related_model_name, model_name)
fk_name, index_name = None, None
class Migration(migrations.Migration):
operations = [
migrations.AddField(
model_name=model_name,
name='id',
field=models.IntegerField(null=True),
preserve_default=True,
),
migrations.RunPython(do_most_of_the_surgery),
migrations.AlterField(
model_name=model_name,
name='id',
field=models.AutoField(
verbose_name='ID', serialize=False, auto_created=True,
primary_key=True),
preserve_default=True,
),
migrations.AlterField(
model_name=model_name,
name='email',
field=models.EmailField(max_length=255, unique=True),
preserve_default=True,
),
migrations.RunPython(do_the_final_lifting),
]
其中
def do_most_of_the_surgery(apps, schema_editor):
models = {}
Model = apps.get_model(app_name, model_name)
# Generate values for the new id column
for i, o in enumerate(Model.objects.all()):
o.id = i + 1
o.save()
models[o.email] = o.id
# Work on the pivot table before going on
drop_constraints_and_indices_in_pivot_table()
# Drop current pk index and create the new one
cursor.execute(
"ALTER TABLE %s DROP PRIMARY KEY" % model_table
)
cursor.execute(
"ALTER TABLE %s ADD PRIMARY KEY (id)" % model_table
)
# Rename the fk column in the pivot table
cursor.execute(
"ALTER TABLE %s "
"CHANGE %s_id %s_id_old %s NOT NULL" %
(pivot_table, model_name, model_name, 'VARCHAR(255)'))
# ... and create a new one for the new id
cursor.execute(
"ALTER TABLE %s ADD COLUMN %s_id INT(11)" %
(pivot_table, model_name))
# Fill in the new column in the pivot table
cursor.execute("SELECT id, %s_id_old FROM %s" % (model_name, pivot_table))
for row in cursor:
id, key = row[0], row[1]
model_id = models[key]
inner_cursor = connection.cursor()
inner_cursor.execute(
"UPDATE %s SET %s_id=%d WHERE id=%d" %
(pivot_table, model_name, model_id, id))
# Drop the old (renamed) column in pivot table, no longer needed
cursor.execute(
"ALTER TABLE %s DROP COLUMN %s_id_old" %
(pivot_table, model_name))
def do_the_final_lifting(apps, schema_editor):
# Create a new unique index for the old pk column
index_prefix = '%s_id' % model_table
new_index_prefix = '%s_email' % model_table
new_index_name = index_name.replace(index_prefix, new_index_prefix)
cursor.execute(
"ALTER TABLE %s ADD UNIQUE KEY %s (%s)" %
(model_table, new_index_name, 'email'))
# Finally, work on the pivot table
recreate_constraints_and_indices_in_pivot_table()
你想介紹一個新列,這應該是一個主鍵和獨特爲此 - 設置默認爲'0'只適用於所有安裝中只有一條記錄的情況 - 您的遷移文件需要爲所有當前記錄填充真實的「id」。文檔應該涵蓋這個主題。 – dahrens
是的,我明白用戶0對所有的ID都不起作用,但我無法在文檔中找到如何填充當前記錄的ID。我檢查了https://docs.djangoproject.com/en/1.10/topics/migrations/;還有其他地方我應該看看? – ygramoel
要填充id字段,我首先需要創建它。正如上面所解釋的,這是遷移/遷移應該做的(據我瞭解),但是失敗了。我無法在創建之前填充id字段,所以我被卡住了。 – ygramoel