#23521: removal of concrete Model from bases doesn't remove it from ModelState
bases
---------------------------------+-------------------------------------
Reporter: Sergey Fedoseev | Owner: Ian Foote
Type: Bug | Status: assigned
Component: Migrations | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
---------------------------------+-------------------------------------
Comment (by Karolis Ryselis):
There is one more case that needs to be addressed related to bases in
migrations.
**Step 1:**
Consider this model:
{{{
class Good(GoodServiceBase):
title = models.CharField(max_length=16)
}}}
this creates migration with the following operation:
{{{
migrations.CreateModel(
name='Good',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True,
serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=16)),
],
),
}}}
**Step 2:**
Then we add a new model and change existing model to inherit from the new
model.
{{{
class GoodServiceBase(models.Model):
active = models.BooleanField(default=True)
class Good(GoodServiceBase):
title = models.CharField(max_length=16)
}}}
This generates migration like this:
{{{
migrations.CreateModel(
name='GoodServiceBase',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True,
serialize=False, verbose_name='ID')),
('active', models.BooleanField(default=True)),
],
),
migrations.RemoveField(
model_name='good',
name='id',
),
migrations.AddField(
model_name='good',
name='goodservicebase_ptr',
field=models.OneToOneField(auto_created=True, default=1,
on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='goods.GoodServiceBase'),
preserve_default=False,
),
}}}
If we have no data in database, this will pass.
**Step 3 with crash:**
Try to access field {{{active}}} in datamigration and migration crashes.
Operation in migration to reproduce this:
{{{
def migrate_my_data(apps, schema_editor):
for good in apps.get_model("goods", "Good").objects.all():
print(good.active)
migrations.RunPython(migrate_my_data, reverse_code=lambda x, y: None)
}}}
This crashes with the error:
{{{
<...>
File "<project home>/goods/migrations/0003_auto_20191025_1157.py", line 8,
in migrate_my_data
print(good.active)
AttributeError: 'Good' object has no attribute 'active'
}}}
As far as I understand this happens because {{{bases}}} is not altered in
migration and fake models do not inherit fields from their true parent
models. Thus, currently if we change inheritance chain of existing models,
we lose the ability to use those models in data migrations.
Tested in version 2.2.6.
--
Ticket URL: <https://code.djangoproject.com/ticket/23521#comment:26>
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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/068.b6f8c638872eaa9a23acc8f9e0dd831c%40djangoproject.com.