I'm having trouble refactoring a superclass in Django v2.2.12 involving three models, with one superclass model and two subclass models:
class BaseProduct(models.Model):
name = models.CharField()
description = models.CharField()
class GeneralProduct(BaseProduct):
pass
class SoftwareProduct(BaseProduct):
pass
The BaseProduct model needs to be renamed to just Product, so I changed this code to:
class Product(models.Model):
name = models.CharField()
description = models.CharField()
class GeneralProduct(Product):
pass
class SoftwareProduct(Product):
pass
And then ran python manage.py makemigrations, in which Django seems to correctly see what changed:
Did you rename the yourapp.BaseProduct model to Product? [y/N] y
Did you rename generalproduct.baseproduct_ptr to generalproduct.product_ptr (a OneToOneField)? [y/N] y
Did you rename softwareproduct.baseproduct_ptr to softwareproduct.product_ptr (a OneToOneField)? [y/N] y
Migrations for 'yourapp':
.../yourapp/migrations/002_auto_20200507_1830.py
- Rename model BaseProduct to Product
- Rename field baseproduct_ptr on generalproduct to product_ptr
- Rename field baseproduct_ptr on softwareproduct to product_ptr
So far so good. Django sees that the superclass got renamed, and it knows that its own autogenerated ..._ptr values that it uses to track model inheritance need to be updated in the db, too.
The resulting migration it comes up with looks about as terse as it should be:
# Generated by Django 2.2.12 on 2020-05-07 18:30
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('yourapp', '0001_initial'),
]
operations = [
migrations.RenameModel(
old_name='BaseProduct',
new_name='Product',
),
migrations.RenameField(
model_name='generalproduct',
old_name='baseproduct_ptr',
new_name='product_ptr',
),
migrations.RenameField(
model_name='softwareproduct',
old_name='baseproduct_ptr',
new_name='product_ptr',
),
]
This all looks perfect, but applying that migration using python manage.py migrate crashes out:
Running migrations:
Applying yourapp.0002_auto_20200507_1830...Traceback (most recent call last):
[...]
File ".../python3.7/site-packages/django/db/migrations/executor.py", line 245, in apply_migration
state = migration.apply(state, schema_editor)
File ".../python3.7/site-packages/django/db/migrations/migration.py", line 114, in apply
operation.state_forwards(self.app_label, project_state)
File ".../python3.7/site-packages/django/db/migrations/operations/models.py", line 340, in state_forwards
state.reload_models(to_reload, delay=True)
File ".../python3.7/site-packages/django/db/migrations/state.py", line 165, in reload_models
self._reload(related_models)
File ".../python3.7/site-packages/django/db/migrations/state.py", line 191, in _reload
self.apps.render_multiple(states_to_be_rendered)
File ".../python3.7/site-packages/django/db/migrations/state.py", line 308, in render_multiple
model.render(self)
File ".../python3.7/site-packages/django/db/migrations/state.py", line 579, in render
return type(self.name, bases, body)
File ".../python3.7/site-packages/django/db/models/base.py", line 253, in __new__
base.__name__,
django.core.exceptions.FieldError: Auto-generated field 'baseproduct_ptr' in class 'SoftwareProduct' for
parent_link to base class 'BaseProduct' clashes with declared field of the same name.
I searched the web for that error, as well as for renaming a Django model that's a superclass for other models, but there does not appear to be any (discoverable) documentation, or blog posts, or SO answers, that talk about this problem.