Django: How to migrate from ManyToMany to ForeignKey?
EDIT First create a DB backup
First create a new temporary FK relationship
_city = models.ForeignKey(...)
and make a migration
python manage.py makemigration
python manage.py migrate
You then need to create a new data migration in the relevant app by creating an empty migration file:
python manage.py makemigration --empty myhouseapp
and in that file manually assign the new relationship from the M2M to the FK. It will look something like:
from django.db import migrations
def save_city_fk(apps, schema):
City = apps.get_model('myapp', 'City')
House = apps.get_model('myapp', 'House')
for house in House.objects.all():
house._city = house.cities.all().first() # Or whatever criterea you want
house._city.save()
def save_city_m2m(apps, schema):
# This should do the reverse
City = apps.get_model('myapp', 'City')
House = apps.get_model('myapp', 'House')
for house in House.objects.all():
if house._city:
house.cities.add(house._city)
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.RunPython(save_city_fk, save_city_m2m)
]
Remove the M2M field, and create another migration.
python manage.py makemigrations
Rename the FK from _city
to city
and create a final migration
python manage.py makemigrations
Then migrate:
python manage.py migrate
Based on Timmy's answer here is what I did:
I added a field like this
city = models.ForeignKey(City, related_name='has_houses', blank=True, null=True)
to avoid therelated_name
for reverse relations and to have the FK blank. Then I ranmakemigrations
andmigrate
.Next, I ran
python manage.py makemigrations --empty houses
because my app is namedhouses
.I added the code for the migration (see below). Then I ran
migrate
.I deleted the M2M field and the
related_name
,null
andblank
constraints and ranmakemigrations
andmigrate
one last time.
Code for the migration:
# -*- coding: utf-8 -*-
# Generated by Django 1.11.15 on 2019-02-15 09:09
from __future__ import unicode_literals
from django.db import migrations
def save_city_fk(apps, schema):
City = apps.get_model('cities', 'City')
House = apps.get_model('houses', 'House')
for house in House.objects.all():
house.city = house.cities.all().first()
house.save()
class Migration(migrations.Migration):
dependencies = [
('houses', '0003_auto_20190215_0949'),
]
operations = [
migrations.RunPython(save_city_fk),
]