views:

656

answers:

2

I have a django app with four models in it. I realize now that one of these models should be in a separate app. I do have south installed for migrations, but I don't think this is something it can handle automatically. How can I migrate one of the models out of the old app into a new one?

Also, keep in mind that I'm going to need this to be a repeatable process, so that I can migrate the production system and such.

+2  A: 

Models aren't very tightly coupled to apps, so moving is fairly simple. Django uses the app name in the name of the database table, so if you want to move your app you can either rename the database table via an SQL ALTER TABLE statement, or - even simpler - just use the db_table parameter in your model's Meta class to refer to the old name.

If you've used ContentTypes or generic relations anywhere in your code so far, you will probably want to rename the app_label of the contenttype pointing at the model that's moving, so that existing relations are preserved.

Of course, if you don't have any data at all to preserve, the easiest thing to do is to drop the database tables completely and run ./manage.py syncdb again.

Daniel Roseman
How do I do that with a south migration?
Apreche
+13  A: 

How to migrate using south.

Lets say we got two apps: common and specific:

myproject/
|-- common
|   |-- migrations
|   |   |-- 0001_initial.py
|   |   `-- 0002_create_cat.py
|   `-- models.py
`-- specific
    |-- migrations
    |   |-- 0001_initial.py
    |   `-- 0002_create_dog.py
    `-- models.py

Now we want to move model common.models.cat to specific app (precisely to specific.models.cat). We do it in the source code and run:

$ python manage.py startmigration specific create_cat --auto
 + Added model 'specific.cat'
$ python manage.py startmigration common drop_cat --auto
 - Deleted model 'common.cat'

myproject/
|-- common
|   |-- migrations
|   |   |-- 0001_initial.py
|   |   |-- 0002_create_cat.py
|   |   `-- 0003_drop_cat.py
|   `-- models.py
`-- specific
    |-- migrations
    |   |-- 0001_initial.py
    |   |-- 0002_create_dog.py
    |   `-- 0003_create_cat.py
    `-- models.py

Now we need to edit moth migration files:

#0003_create_cat: replace existing forward and backward code to use just one sentence:

def forwards(self, orm):
    db.rename_table('common_cat', 'specific_cat') 
def backwards(self, orm):
    db.rename_table('specific_cat', 'common_cat')


#0003_drop_cat:replace existing forward and backward code to use just one sentence; add dependency:

depends_on = (
    ('specific', '0003_create_cat'),
)
def forwards(self, orm):
    pass
def backwards(self, orm):
    pass

Now both apps migrations are aware of the change and life sucks just a little less :-) Setting this relationship between migrations is key of success. Now if you do:

python manage.py migrate common
 > specific: 0003_create_cat
 > common: 0003_drop_cat

will do both migration, and

python manage.py migrate specific 0002_create_dog
 < common: 0003_drop_cat
 < specific: 0003_create_cat

will migrate things down.

Notice that for uprading of schema I used common app and for downgrading, I used specific app. That's because how the dependency here works.

Potr Czachur
Wow, thanks. I learned south on my own since asking this question, but I'm sure this will greatly help others.
Apreche