将字段更改为多对多时的 Django 数据迁移 [英] Django data migration when changing a field to ManyToMany

查看:19
本文介绍了将字段更改为多对多时的 Django 数据迁移的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Django 应用程序,我想在其中将字段从 ForeignKey 更改为 ManyToManyField.我想保留我的旧数据.为此,最简单/最好的流程是什么?如果重要的话,我使用 sqlite3 作为我的数据库后端.

I have a Django application in which I want to change a field from a ForeignKey to a ManyToManyField. I want to preserve my old data. What is the simplest/best process to follow for this? If it matters, I use sqlite3 as my database back-end.

如果我对问题的总结不清楚,这里有一个例子.假设我有两个模型:

If my summary of the problem isn't clear, here is an example. Say I have two models:

class Author(models.Model):  
    author = models.CharField(max_length=100) 

class Book(models.Model):  
    author = models.ForeignKey(Author)  
    title = models.CharField(max_length=100)

假设我的数据库中有很多数据.现在,我想按如下方式更改 Book 模型:

Say I have a lot of data in my database. Now, I want to change the Book model as follows:

class Book(models.Model):  
    author = models.ManyToManyField(Author)  
    title = models.CharField(max_length=100) 

我不想丢失"我之前的所有数据.

I don't want to "lose" all my prior data.

实现这一目标的最佳/最简单的方法是什么?

What is the best/simplest way to accomplish this?

推荐答案

我意识到这个问题很老了,当时数据迁移的最佳选择是使用 South.现在Django有自己的migrate命令,过程略有不同.

I realize this question is old and at the time the best option for Data Migrations was using South. Now Django has its own migrate command, and the process is slightly different.

我已将这些模型添加到名为 books 的应用中——如果您的情况不是这样,请相应地进行调整.

I've added these models to an app called books -- adjust accordingly if that's not your case.

首先,将字段添加到 Book 并将 related_name 添加到至少一个或两个(否则它们会发生冲突):

First, add the field to Book and a related_name to at least one, or both of them (or they'll clash):

class Book(models.Model):  
    author = models.ForeignKey(Author, related_name='book')
    authors = models.ManyToManyField(Author, related_name='books')
    title = models.CharField(max_length=100) 

生成迁移:

$ ./manage.py makemigrations
Migrations for 'books':
  0002_auto_20151222_1457.py:
    - Add field authors to book
    - Alter field author on book

现在,创建一个空的迁移来保存数据本身的迁移:

Now, create an empty migration to hold the migration of the data itself:

./manage.py makemigrations books --empty
    Migrations for 'books':
0003_auto_20151222_1459.py:

并在其中添加以下内容.要准确了解其工作原理,请查看有关数据迁移.注意不要覆盖迁移依赖.

And add the following content to it. To understand exactly how this works, check the documentation on Data Migrations. Be careful not to overwrite the migration dependency.

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations


def make_many_authors(apps, schema_editor):
    """
        Adds the Author object in Book.author to the
        many-to-many relationship in Book.authors
    """
    Book = apps.get_model('books', 'Book')

    for book in Book.objects.all():
        book.authors.add(book.author)


class Migration(migrations.Migration):

    dependencies = [
        ('books', '0002_auto_20151222_1457'),
    ]

    operations = [
        migrations.RunPython(make_many_authors),
    ]

现在从模型中删除 author 字段——它应该是这样的:

Now remove the author field from the Model -- it should look like this:

class Book(models.Model):
    authors = models.ManyToManyField(Author, related_name='books')
    title = models.CharField(max_length=100)

为此创建一个新的迁移,并运行它们:

Create a new migration for that, and run them all:

$ ./manage.py makemigrations
Migrations for 'books':
  0004_remove_book_author.py:
    - Remove field author from book

$ ./manage.py migrate
Operations to perform:
  Synchronize unmigrated apps: messages, staticfiles
  Apply all migrations: admin, auth, sessions, books, contenttypes
Synchronizing apps without migrations:
  Creating tables...
    Running deferred SQL...
  Installing custom SQL...
Running migrations:
  Rendering model states... DONE
  Applying books.0002_auto_20151222_1457... OK
  Applying books.0003_auto_20151222_1459... OK
  Applying books.0004_remove_book_author... OK

就是这样.以前在 book.author 中可用的作者现在应该在您从 book.authors.all() 获得的查询集中.

And that's it. The authors previously available at book.author now should be in the queryset you get from book.authors.all().

这篇关于将字段更改为多对多时的 Django 数据迁移的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆