Migrating data from "Many-To-Many" to "Many-To-Many Through" in django

django, django-models, django-south

Solution

Create your intermediate model without any extra fields, for now. Give it a unique constraint to match the existing one and specify the table name to match the existing one:

class CategoryEntry(models.Model):
    category = models.ForeignKey(Category)
    entry = models.ForeignKey(Entry)   

    class Meta:
        db_table='main_category_entries'   #change main_ to your application
        unique_together = (('category', 'entry'))

Run the South schema migration.

Edit the generated schema migration script and comment-out all the forwards and backwards entries, since you'll be re-using the existing intersection table. Add `pass` to complete the methods.

Run the migration.

Update any existing code. As it says in https://docs.djangoproject.com/en/dev/topics/db/models/#many-to-many-relationships, "Unlike normal many-to-many fields, you can't use add, create, or assignment to create relationships" so you'll need to modify any existing application code, e.g.

c.entry.add(e)

could become:

try:
    categoryentry = c.categoryentry_set.get(entry = e)
except CategoryEntry.DoesNotExist:
    categoryentry = CategoryEntry(category=c, entry=e)
    categoryentry.save()

and:

e.category_entries.add(c)

could become:

categoryentry = CategoryEntry(category=c, entry=e)  #set extra fields here
categoryentry.save()                

and:

c.entry.remove(e)

could become:

categoryentry = c.categoryentry_set.get(entry = e)
categoryentry.delete()

Once this initial pseudo migration has been done, you should then be able to add the extra fields to the `CategoryEntry` and create further migrations as normal.

Problem

I've got a model ``` class Category(models.Model): title = models.CharField(...) entry = models.ManyToManyField(Entry,null=True,blank=True, related_name='category_entries', ) ``` That I wish to refactor to have additional data with each relationship: ``` class Category(models.Model): title = models.CharField(...) entry = models.ManyToManyField(Entry,null=True,blank=True, related_name='category_entries', through='CategoryEntry', ) ``` But south deletes the existing table. How can I preserve the existing m-t-m relationships?

Original source

Related problems