问题
I was working on an app that is supposed to send newsletters to customers. I had a model defined like this
from django.auth.models import User
class Newsletter(models.Model):
owner = models.ForeignKey(User, related_name='+', blank=False)
sent = models.BooleanField(default=False)
date_created = models.DateTimeField(auto_now_add=True)
date_sent = models.DateTimeField(null=True)
subject = models.CharField(max_length=255)
content = HTMLField()
recipients = models.ManyToManyField(User, related_name='+')
Later on, I found out that I might need to send these to people who do not have user accounts, so I defined an email model
class Email(models.Model):
email = models.CharField(max_length=255)
and changed the recipients field to read
recipients = models.ManyToManyField(Email, related_name='+')
After this, I ran schemamigration command, but South claimed that there are no changes. I have made several attempts to manually manipulate tables and indexes, but at some point figured that since it is a new app, I can just drop all the existing tables, remove all igrations and recreate initial migration from scratch. This poses a question though, how do I do a migration like this if I really need to preserve the data.
回答1:
If you need to preserve data you will need to split it into 3 migrations (schema, data, schema) like this:
class Migration(SchemaMigration):
def forwards(self, orm):
db.add_column(
u'yourapp_newsletter_recipients',
'email_id',
self.gf(
'django.db.models.fields.related.ForeignKey'
)(to=orm.Email)
)
Notice that you should have your old schema in the migration's models property.
Then your data migration that fills the email field. Then schema migration again:
class Migration(SchemaMigration):
def forwards(self, orm):
db.delete_column(u'yourapp_newsletter_recipients', 'user_id')
In this one you should already have correct m2m field for recipients field in the migration's models['newslatter']
来源:https://stackoverflow.com/questions/13755119/south-migrations-and-changes-to-many-to-may-fields