手动迁移
有时,Django 生成的迁移是不够的。当你想要进行数据迁移时尤其如此。
例如,让我们有这样的模型:
class Article(models.Model):
title = models.CharField(max_length=70)
此模型已有现有数据,现在你要添加 SlugField
:
class Article(models.Model):
title = models.CharField(max_length=70)
slug = models.SlugField(max_length=70)
你创建了迁移以添加字段,但现在你想根据他们的 title
为所有现有文章设置 slug。
当然,你可以在终端中执行以下操作:
$ django-admin shell
>>> from my_app.models import Article
>>> from django.utils.text import slugify
>>> for article in Article.objects.all():
... article.slug = slugify(article.title)
... article.save()
...
>>>
但是你必须在所有的环境中(例如你的办公室桌面,你的笔记本电脑……)这样做,你的所有同事也必须这样做,你必须在分期和推动时考虑它。生活。
为了一劳永逸,我们将在迁移中实现。首先创建一个空迁移:
$ django-admin makemigrations --empty app_name
这将创建一个空的迁移文件。打开它,它包含一个基础骨架。假设你之前的迁移被命名为 0023_article_slug
,这个名字叫 0024_auto_20160719_1734
。以下是我们将在迁移文件中编写的内容:
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-07-19 15:34
from __future__ import unicode_literals
from django.db import migrations
from django.utils.text import slugify
def gen_slug(apps, schema_editor):
# We can't import the Article model directly as it may be a newer
# version than this migration expects. We use the historical version.
Article = apps.get_model('app_name', 'Article')
for row in Article.objects.all():
row.slug = slugify(row.name)
row.save()
class Migration(migrations.Migration):
dependencies = [
('hosting', '0023_article_slug'),
]
operations = [
migrations.RunPython(gen_slug, reverse_code=migrations.RunPython.noop),
# We set `reverse_code` to `noop` because we cannot revert the migration
# to get it back in the previous state.
# If `reverse_code` is not given, the migration will not be reversible,
# which is not the behaviour we expect here.
]