有时,由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。
当然,您可以在终端中执行以下操作:
$ 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 fromdjango.dbimport 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. ]