Creating through table after setting initial many2many

I’m working on a database that has several many to many relationships. Most of them have a through table defined explicitly in models.py, but a couple recent ones do not, and I want to add those in to make it easier to write APIs, for clarity, and for enabling constraints and other alterations.

The makemigrations command worked fine, but when attempting to migrate I get an error saying
django.db.utils.ProgrammingError: relation “<linking_table_name>” already exists.

The linking table in question already has some populated data, so I don’t want to delete the table and recreate the linking table, unless there’s a fast and easy solution for saving and re-uploading the data.

Ideally I’d like a way to tell django that I’m (functionally speaking, don’t know about the precise mechanics) not trying to create an entirely new table, just define it explicitly in models.py with a minor alteration (uniqueness constraint)

Thanks for your help!

I tried playing with this, and I think I got it to work by:

  1. Find the name of the automatically-created join-table.
  2. Create a model matching the structure of the join-table
    1. Set the db_table attribute in Meta
    2. Set the db_column attributes on the ForeignKey columns (unless you use the names for those fields that would create those column names in the table).
    3. Do not introduce any changes to this table at this time.
  3. Add the through parameter to your ManyToManyField pointing to this new model.
  4. Do makemigrations to create the migration for these changes.
  5. Since the table and columns already exist, do a migrate --fake for this migration
  6. Add your other attributes to the join table. (Note, you may need to set defaults or null=True for these newly-created fields.)
  7. Do your next makemigrations and migrate to add these changes.

Disclaimer, I strongly suggest you test this out thoroughly on a copy of your database. I think I captured all the steps I took, but I won’t deny the possibility that I missed one. Also, that I got it to work for me on my little toy database isn’t necessarily a guarantee that it’s going to work for you. There may be some edge cases or existing conditions that would make it break in a more realistic scenario.
(Note: If you do try this, I’m quite interested in hearing about your results.)

Thanks for your help, I’ll give it a try today and get back to you.

Do you think it’s sufficient to simply make a backup of the database tables that I can restore from if there are any issues? Or do you think that the problems would potentially be more pervasive/subtle than that?

I’d also be concerned that I could recover my source code to its state prior to making changes. But yes, with complete backups of both code and data, I think you’d probably be ok.

Sorry, took a little longer than expected to get around to implementing it, but it looks like it worked perfectly- tables are created, and data is preserved. Thanks!

1 Like