#28193: Maximum length of database column in many-to-many through table is not updated if the foreign keyed model has a CharField primary key -------------------------------------+------------------------------------- Reporter: James Hiew | Owner: nobody Type: Bug | Status: new Component: Migrations | Version: 1.11 Severity: Normal | Resolution: Keywords: manytomanyfield, | Triage Stage: primary key, varchar, max length | Unreviewed Has patch: 0 | Needs documentation: 0 Needs tests: 0 | Patch needs improvement: 0 Easy pickings: 0 | UI/UX: 0 -------------------------------------+-------------------------------------
Old description: > If you have a model `Foo`with a `CharField` primary key, and then another > model `Bar` which has a `ManyToManyField` relationship with `Foo`, any > changes to the `max_length` of `Foo`'s primary key is not reflected in > the max string length of the corresponding Bar-Foo m2m table column. > > Starting with the below minimal example > ``` > from django.db import models > > class Foo(models.Model): > code = models.CharField(max_length=15, primary_key=True, unique=True, > auto_created=False, editable=False) > name = models.CharField(max_length=100) > > class Bar(models.Model): > foos = models.ManyToManyField(Foo) > ``` > > Run `./manage.py makemigrations` then `./manage.py migrate`. > > Change the `max_length` of `Foo.code` to a higher value e.g. 100 > ``` > from django.db import models > > class Foo(models.Model): > code = models.CharField(max_length=100, primary_key=True, > unique=True, auto_created=False, editable=False) > name = models.CharField(max_length=100) > > class Bar(models.Model): > foos = models.ManyToManyField(Foo) > ``` > Run `./manage.py makemigrations` then `./manage.py migrate` once more. > > The final `myapp_bar_foos` table DDL is: > > ``` > CREATE TABLE "myapp_bar_foos" ("id" integer NOT NULL PRIMARY KEY > AUTOINCREMENT, "bar_id" integer NOT NULL REFERENCES "myapp_bar" ("id"), > "foo_id" varchar(15) NOT NULL REFERENCES "myapp_foo" ("code")); > CREATE UNIQUE INDEX "myapp_bar_foos_bar_id_foo_id_6037806e_uniq" ON > "myapp_bar_foos" ("bar_id", "foo_id"); > CREATE INDEX "myapp_bar_foos_bar_id_f5103189" ON "myapp_bar_foos" > ("bar_id"); > CREATE INDEX "myapp_bar_foos_foo_id_84900b21" ON "myapp_bar_foos" > ("foo_id") > ``` > > The `foo_id` column should have been updated to type `varchar(100)` but > it remains as `varchar(15)`. > > The problem is not noticeable when using SQLite (e.g. during local > development), as SQLite doesn't seem to enforce the varchar length > constraints, but Postgres does, so this issue is pernicious when moving > to production. New description: If you have a model `Foo`with a `CharField` primary key, and then another model `Bar` which has a `ManyToManyField` relationship with `Foo`, any changes to the `max_length` of `Foo`'s primary key is not reflected in the max string length of the corresponding Bar-Foo m2m table column. Starting with the below minimal example {{{ from django.db import models class Foo(models.Model): code = models.CharField(max_length=15, primary_key=True, unique=True, auto_created=False, editable=False) name = models.CharField(max_length=100) class Bar(models.Model): foos = models.ManyToManyField(Foo) }}} Run `./manage.py makemigrations` then `./manage.py migrate`. Change the `max_length` of `Foo.code` to a higher value e.g. 100 {{{ from django.db import models class Foo(models.Model): code = models.CharField(max_length=100, primary_key=True, unique=True, auto_created=False, editable=False) name = models.CharField(max_length=100) class Bar(models.Model): foos = models.ManyToManyField(Foo) }}} Run `./manage.py makemigrations` then `./manage.py migrate` once more. The final `myapp_bar_foos` table DDL is: {{{ CREATE TABLE "myapp_bar_foos" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "bar_id" integer NOT NULL REFERENCES "myapp_bar" ("id"), "foo_id" varchar(15) NOT NULL REFERENCES "myapp_foo" ("code")); CREATE UNIQUE INDEX "myapp_bar_foos_bar_id_foo_id_6037806e_uniq" ON "myapp_bar_foos" ("bar_id", "foo_id"); CREATE INDEX "myapp_bar_foos_bar_id_f5103189" ON "myapp_bar_foos" ("bar_id"); CREATE INDEX "myapp_bar_foos_foo_id_84900b21" ON "myapp_bar_foos" ("foo_id") }}} The `foo_id` column should have been updated to type `varchar(100)` but it remains as `varchar(15)`. The problem is not noticeable when using SQLite (e.g. during local development), as SQLite doesn't seem to enforce the varchar length constraints, but Postgres does, so this issue is pernicious when moving to production. -- Comment (by James Hiew): Fix formatting -- Ticket URL: <https://code.djangoproject.com/ticket/28193#comment:3> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/067.ff6c431480f2eb6bf75aca4accca9543%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.