I have an existing Django project that has several models using concrete inheritance of a base class. After closer consideration, and after reading about what people like Jacob Kaplan-Moss have to say about it, using this concrete inheritance is unnecessary in my case. I would like to migrate to using an abstract base class instead.
The thing that makes this complicated is that my site is live and I have user entered data. Thus, I'll need to keep all my data intact throughout this transition.
I'll give an example to be more concrete:
Before:
app1/models.py:
class Model1(base_app.models.BaseModel):
field1 = models.CharField(max_length=1000)
field2 = models.CharField(max_length=1000)
app2/models.py:
class Model2(base_app.models.BaseModel):
field1 = models.CharField(max_length=1000)
field2 = models.CharField(max_length=1000)
base_app/models.py:
class BaseModel(models.Model):
user = models.ForeignKey(User)
another_field = models.CharField(max_length=1000)
After:
app1/models.py:
class Model1(base_app.models.BaseModel):
field1 = models.CharField(max_length=1000)
field2 = models.CharField(max_length=1000)
app2/models.py:
class Model2(base_app.models.BaseModel):
field1 = models.CharField(max_length=1000)
field2 = models.CharField(max_length=1000)
base_app/models.py:
class BaseModel(models.Model):
user = models.ForeignKey(User)
another_field = models.CharField(max_length=1000)
class Meta:
abstract = True
Right now, my plan is to first add the abstract = True
to the BaseModel. Then,for each model that uses BaseModel
, one at a time:
- Use south to migrate the database and create this migration using the --auto flag
- Use a south data migration. For instance, I would loop through each object in Model1 to fetch the object in BaseModel that has the same pk and copy the values for each field of the BaseModel object to the Model1 object.
So first, will this work? And second, is there a better way to do this?
Update:
My final solution is described in detail here:
http://www.markliu.me/2011/aug/23/migrating-a-django-postgres-db-from-concrete-inhe/
class Meta: abstract = True
on yourBaseModel
, not on his descendants. docs.djangoproject.com/en/1.3/topics/db/models/… – Etienne