I'd like to migrate data from a ManyToMany-Field to a ForeignKey-Field. Since I migrated the data in the other direction (from ForeignKey to ManyToMany) in a previous migration and will deploy both migrations in one step, I guess this should work.
I had this model:
class Log(models.Model):
contacts = models.ManyToManyField(Contact, related_name='contact_logs', blank=True, null=True)
I added the new field:
class Log(models.Model):
contact = models.ForeignKey(Contact, blank=True, null=True)
contacts = models.ManyToManyField(Contact, related_name='contact_logs', blank=True, null=True)
Then I did:
$ ./manage.py schemamigration myapp --auto
$ ./manage.py datamigration myapp move_contacts_data
And now I try to write the data-migration. This is how I previously migrated the data from ForeignKey to ManyToMany:
def forwards(self, orm):
"Write your forwards methods here."
for log in orm.Log.objects.all():
if log.contacts:
log.contact.add(log.contacts)
log.save()
But this doesn't seem to work the other way around. I get:
$ ./manage.py migrate myapp :(
Running migrations for myapp:
- Migrating forwards to 0072_move_contacts_data.
contacts:0072_move_contacts_data
Error in migration: myapp:0072_move_contacts_data
AttributeError: 'NoneType' object has no attribute 'add'
Can anybody help me out?
If your m2m relation only contains a single contact for each log, you can just do the following:
def forwards(self, orm):
"Write your forwards methods here."
for log in orm.Log.objects.all():
if log.contacts.all():
assert log.contacts.count() == 1
log.contact = log.contacts.get()
log.save()
If the relation contains more than one contact, you'll have to define a way to determine which contact you want to save. This can be by some arbitrary date field or any other field. Either way, you will lose some data. How to handle that is up to you.