[Django] #27860: Changing a CharField to a ForeignKey explodes when migrating in PostgreSQL

53 views
Skip to first unread message

Django

unread,
Feb 18, 2017, 1:37:54 PM2/18/17
to django-...@googlegroups.com
#27860: Changing a CharField to a ForeignKey explodes when migrating in PostgreSQL
-----------------------------------------+----------------------------
Reporter: Daniel Quinn | Owner: nobody
Type: Uncategorized | Status: new
Component: Migrations | Version: 1.10
Severity: Normal | Keywords: PostgreSQL
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+----------------------------
If I have a model that looks like this:

{{{
class MyModel(models.Model):
my_field = models.CharField(max_length=128, db_index=True)
}}}

`makemigrations` will create a migration that looks like this:

{{{
migrations.CreateModel(
name='MyModel',
fields=[
('id', models.AutoField(auto_created=True,
primary_key=True, serialize=False, verbose_name='ID')),
('my_field', models.CharField(db_index=True,
max_length=128)),
],
),
}}}

However, if I later change the field to a `ForeignKey`:

{{{
class MyModel(models.Model):
my_field = models.ForeignKey("alpha.MyOtherModel", blank=True)
}}}

`makemigrations` will create this:

{{{
migrations.AlterField(
model_name='mymodel',
name='my_field',
field=models.ForeignKey(blank=True,
on_delete=django.db.models.deletion.CASCADE, to='alpha.MyOtherModel'),
),
}}}

...which explodes in PostgreSQL (but not SQLite or MySQL) with this:

{{{
psycopg2.ProgrammingError: operator class "varchar_pattern_ops" does not
accept data type integer
}}}

The fix (at least for my case) was to manually break up the `AlterField`
into separate `RemoveField` and `AddField` steps like this:

{{{
migrations.RemoveField(
model_name='mymodel',
name='my_field',
),
migrations.AddField(
model_name='mymodel',
name='my_field',
field=models.ForeignKey(blank=True,
on_delete=django.db.models.deletion.CASCADE, to='alpha.MyOtherModel'),
),
}}}

I ran into this on my own GPL project, and the issue history wherein we
found and fixed the problem is here:
https://github.com/danielquinn/paperless/issues/183

--
Ticket URL: <https://code.djangoproject.com/ticket/27860>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Feb 20, 2017, 10:02:13 AM2/20/17
to django-...@googlegroups.com
#27860: Changing a CharField to a ForeignKey explodes when migrating in PostgreSQL
-------------------------------+--------------------------------------

Reporter: Daniel Quinn | Owner: nobody
Type: Uncategorized | Status: new
Component: Migrations | Version: 1.10
Severity: Normal | Resolution:

Keywords: PostgreSQL | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------

Comment (by Tim Graham):

I couldn't reproduce a problem with these final models:
{{{
class CharPK(models.Model):
id = models.CharField(primary_key=True, max_length=128)

class MyModel(models.Model):
my_field = models.ForeignKey(CharPK, max_length=128,
on_delete=models.CASCADE)
}}}
Does "alpha.MyOtherModel" have a `CharField` primary key?

I'm not sure what the proper resolution would be here, considering that
automatically generating `RemoveField` / `AddField` would be data loss
operations.

--
Ticket URL: <https://code.djangoproject.com/ticket/27860#comment:1>

Django

unread,
Feb 20, 2017, 10:14:45 AM2/20/17
to django-...@googlegroups.com
#27860: Changing a CharField to a ForeignKey explodes when migrating in PostgreSQL
-------------------------------+--------------------------------------

Reporter: Daniel Quinn | Owner: nobody
Type: Uncategorized | Status: new
Component: Migrations | Version: 1.10
Severity: Normal | Resolution:

Keywords: PostgreSQL | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------

Old description:

New description:

If I have a model that looks like this:

{{{
class MyModel(models.Model):
my_field = models.CharField(max_length=128, db_index=True)
}}}

`makemigrations` will create a migration that looks like this:

{{{
migrations.CreateModel(
name='MyModel',
fields=[
('id', models.AutoField(auto_created=True,
primary_key=True, serialize=False, verbose_name='ID')),
('my_field', models.CharField(db_index=True,
max_length=128)),
],
),
}}}

However, if I later change the field to a `ForeignKey`:

{{{
class MyOtherModel(models.Model):
stuff = models.CharField(max_length=128)

`makemigrations` will create this:

--

Comment (by Daniel Quinn):

`alpha.MyOtherModel` is using a default numeric key. Sorry, I should have
included that in the ticket and so I've modified it to include the
`MyOtherModel` class.

The problem is that migrations is doing an `alter` for a field that
changed not just from a `CharField` to a `ForeignKeyField` but rather to a
foreign key of a different type. SQLite and MySQL somehow didn't have a
problem with this, but PostgreSQL exploded.

Perhaps a solution would be a warning stage not unlike the prompt you get
when trying to add a field with no `default=` value? Something like:

> It looks like you've changed a CharField to a ForeignKey of a different
type. This will generate an AddField and RemoveField. Is that cool with
you?

--
Ticket URL: <https://code.djangoproject.com/ticket/27860#comment:2>

Django

unread,
Feb 20, 2017, 10:36:21 AM2/20/17
to django-...@googlegroups.com
#27860: Changing a CharField to a ForeignKey crashes when migrating in PostgreSQL
------------------------------+------------------------------------

Reporter: Daniel Quinn | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: 1.10
Severity: Normal | Resolution:
Keywords: PostgreSQL | Triage Stage: Accepted

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+------------------------------------
Changes (by Tim Graham):

* type: Uncategorized => Bug
* stage: Unreviewed => Accepted


Comment:

It looks like the `varchar_pattern_ops` index needs to be dropped before
altering the field.

--
Ticket URL: <https://code.djangoproject.com/ticket/27860#comment:3>

Django

unread,
Mar 1, 2017, 8:18:54 AM3/1/17
to django-...@googlegroups.com
#27860: Changing a CharField to a ForeignKey crashes when migrating in PostgreSQL
------------------------------+------------------------------------
Reporter: Daniel Quinn | Owner: felixxm
Type: Bug | Status: assigned
Component: Migrations | Version: 1.10

Severity: Normal | Resolution:
Keywords: PostgreSQL | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+------------------------------------
Changes (by felixxm):

* owner: nobody => felixxm
* status: new => assigned


--
Ticket URL: <https://code.djangoproject.com/ticket/27860#comment:4>

Django

unread,
Mar 2, 2017, 4:48:51 PM3/2/17
to django-...@googlegroups.com
#27860: Changing a CharField to a ForeignKey crashes when migrating in PostgreSQL
------------------------------+------------------------------------
Reporter: Daniel Quinn | Owner: felixxm
Type: Bug | Status: assigned
Component: Migrations | Version: 1.10

Severity: Normal | Resolution:
Keywords: PostgreSQL | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+------------------------------------
Changes (by felixxm):

* has_patch: 0 => 1


Comment:

[https://github.com/django/django/pull/8140 PR]

--
Ticket URL: <https://code.djangoproject.com/ticket/27860#comment:5>

Django

unread,
Mar 3, 2017, 10:50:48 AM3/3/17
to django-...@googlegroups.com
#27860: Changing a CharField to a ForeignKey crashes when migrating in PostgreSQL
------------------------------+------------------------------------
Reporter: Daniel Quinn | Owner: felixxm
Type: Bug | Status: assigned
Component: Migrations | Version: 1.10

Severity: Normal | Resolution:
Keywords: PostgreSQL | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+------------------------------------

Comment (by Tim Graham <timograham@…>):

In [changeset:"6b47431aaf5222b687791f92f352413a16fc62cd" 6b47431]:
{{{
#!CommitTicketReference repository=""
revision="6b47431aaf5222b687791f92f352413a16fc62cd"
Refs #27860 -- Simplified deleting indexes on PostgreSQL using "IF
EXISTS".
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/27860#comment:6>

Django

unread,
May 24, 2017, 1:26:22 AM5/24/17
to django-...@googlegroups.com
#27860: Changing a CharField to a ForeignKey crashes when migrating in PostgreSQL
------------------------------+------------------------------------
Reporter: Daniel Quinn | Owner: felixxm
Type: Bug | Status: closed
Component: Migrations | Version: 1.10
Severity: Normal | Resolution: fixed

Keywords: PostgreSQL | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+------------------------------------
Changes (by GitHub <noreply@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"91b2bc3e70be2632baad86488fb03cf02848b5b6" 91b2bc3]:
{{{
#!CommitTicketReference repository=""
revision="91b2bc3e70be2632baad86488fb03cf02848b5b6"
Fixed #27860 -- Dropped varchar_pattern_ops/text_pattern_ops index before
altering char/text field in PostgreSQL.

Thanks Tim Graham for the review.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/27860#comment:7>

Reply all
Reply to author
Forward
0 new messages