Opened 3 weeks ago

Closed 3 weeks ago

Last modified 3 weeks ago

#36800 closed Bug (fixed)

Issue with ManyToManyField renaming

Reported by: Josik Owned by: Clifford Gama
Component: Database layer (models, ORM) Version: 6.0
Severity: Release blocker Keywords:
Cc: Ryan P Kilby Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Since Django 6.0, using Postgres 16 database, when a ManyToManyField is renamed, it cannot be access anymore.

Models before field renaming:

from django.db import models


class Book(models.Model):
    title = models.CharField(max_length=200)


class Author(models.Model):
    name = models.CharField()
    books = models.ManyToManyField(Book)

In Postgres database I have the following table for the m2m relation my_app_author_books.

I then renamed the m2m field "books" to "volumes":

from django.db import models


class Book(models.Model):
    title = models.CharField(max_length=200)


class Author(models.Model):
    name = models.CharField()
    volumes = models.ManyToManyField(Book)

This generates the following migration:

# Generated by Django 6.0 on 2025-12-15 10:04

from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('my_app', '0001_initial'),
    ]

    operations = [
        migrations.RenameField(
            model_name='author',
            old_name='books',
            new_name='volumes',
        ),
    ]

In Postgres database I still have the following table for the m2m relation my_app_author_books. The table was not renamed to my_app_author_volumes which was the case in Django 5.2.

Maybe this is a new behaviour but when I get all instances of volumes, in shell_plus:

author_instance.volumes.all()
gives

ProgrammingError: relation "my_app_author_volumes" does not exist
LINE 1: ...y_app_book"."title" FROM "my_app_book" INNER JOIN "my_app_au...

Migrations were played

python manage.py showmigrations gives:

my_app
 [X] 0001_initial
 [X] 0002_rename_books_author_volumes

Change History (13)

comment:1 by karyon, 3 weeks ago

I saw this too. sqlmigrate in 5.2 outputs something like

-- Rename field degrees on course to programs
-- Rename field books on author to volumes
--
ALTER TABLE "my_app_author_books" RENAME TO "my_app_author_volumes";

With 6.0, the ALTER TABLE line is replaced by -- (no-op).

Adding this to the migration works around it:

    migrations.RunSQL(
        sql='ALTER TABLE "my_app_author_books" RENAME TO "my_app_author_volumes";',
        reverse_sql='ALTER TABLE "my_app_author_volumes" RENAME TO "my_app_author_books";',
    ),

comment:2 by Clifford Gama, 3 weeks ago

Owner: set to Clifford Gama
Severity: NormalRelease blocker
Status: newassigned
Triage Stage: UnreviewedAccepted

Thanks for the report! I haven't bisected yet but I tested against both 5.2. and 6.0 and reproduced the issue in the latter.

comment:4 by ericmuijs, 3 weeks ago

I think I'm also having the same issue. I had a many to many field and a test fixture. With django 6 im unable to load the fixture: error is that the table does not exists. Difference in naming is the cause:

Naming of many to many table

  1. Dev Database (tables created by django 5) : base_vergunningproductgroep_producten (plural)
  2. Test database (tables created by django 6) : base_vergunningproductgroep_product

Code highlighting:

class VergunningProductGroep(TenantModel):
  vergunning = models.ForeignKey(Vergunning, on_delete=models.CASCADE, related_name='vergunningproducten')
  producten = models.ManyToManyField(Product, related_name='vergunningproductgroepen')

comment:5 by Natalia Bidart, 3 weeks ago

Cc: Ryan P Kilby Simon Charette added

comment:6 by Clifford Gama, 3 weeks ago

Has patch: set

comment:7 by Simon Charette, 3 weeks ago

Cc: Simon Charette removed

Not sure why I was pinged here and on Discord if there was already a patch, it gave me the impression there was an urgent need for me to look at this.

The proposed solution looks right to me albeit we might want to adjust the comment about no field alteration needed to take place if the name change as that's no true for many-to-many fields and likely what made us miss this in the first place.

Here's where I got during my plane trip.

comment:8 by Pravin M D, 3 weeks ago

Thanks for the report! I'm also having the same issue.

comment:9 by Jacob Walls, 3 weeks ago

Triage Stage: AcceptedReady for checkin

comment:10 by Jacob Walls, 3 weeks ago

Patch needs improvement: set
Triage Stage: Ready for checkinAccepted

An Oracle failure to check.

comment:11 by Jacob Walls, 3 weeks ago

Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

comment:12 by Jacob Walls <jacobtylerwalls@…>, 3 weeks ago

Resolution: fixed
Status: assignedclosed

In 6cc1231:

Fixed #36800 -- Restored ManyToManyField renaming in BaseDatabaseSchemaEditor.alter_field().

Regression in f9a44cc0fac653f8e0c2ab1cdfb12b2cc5c63fc2.

Now that ManyToManyField is no longer concrete the decision of whether or not
it should be altered, which is also relied on by field renaming, should take
into consideration name changes even if it doesn't have a column associated
with it, as auto-created many-to-many relationship table names are a base of it.

Note that there is room for optimization here where a rename can be entirely
avoided if ManyToManyField.db_table remains stable between .name changes, just
like we do with Field.db_column remaining stable, but since this is a
regression and meant to be backported the current patch focuses on correctness
over further improvements.

Thanks Josik for the report.

Co-authored-by: Simon Charette <charette.s@…>

comment:13 by Jacob Walls <jacobtylerwalls@…>, 3 weeks ago

In ba7f49c:

[6.0.x] Fixed #36800 -- Restored ManyToManyField renaming in BaseDatabaseSchemaEditor.alter_field().

Regression in f9a44cc0fac653f8e0c2ab1cdfb12b2cc5c63fc2.

Now that ManyToManyField is no longer concrete the decision of whether or not
it should be altered, which is also relied on by field renaming, should take
into consideration name changes even if it doesn't have a column associated
with it, as auto-created many-to-many relationship table names are a base of it.

Note that there is room for optimization here where a rename can be entirely
avoided if ManyToManyField.db_table remains stable between .name changes, just
like we do with Field.db_column remaining stable, but since this is a
regression and meant to be backported the current patch focuses on correctness
over further improvements.

Thanks Josik for the report.

Co-authored-by: Simon Charette <charette.s@…>

Backport of 6cc1231285a20b11058143f8cb0a6b4b3999b23a from main.

Note: See TracTickets for help on using tickets.
Back to Top