| 107 | | This is bad practice. TBC.... |
| | 107 | This is bad practice. Instead, as I described above, you should be making three migrations. Starting with your models.py file in the original state, we should: |
| | 108 | |
| | 109 | * Add the new `first_name` and `last_name` fields. |
| | 110 | * Run `./manage.py startmigration southdemo add_firstlast_name --auto` - this should make a `0003_add_firstlast_name.py` migration. |
| | 111 | * Run `./manage.py startmigration southdemo migrate_names` - this should create `0004_migrate_names.py` (which will just be a blank template, since we gave startmigration no options) |
| | 112 | * Remove the `name` field from models.py. |
| | 113 | * Run `./manage.py startmigration southdemo remove_name --auto` - this will make `0005_remove_name.py`. |
| | 114 | |
| | 115 | This process can be extended to any kind of migration - do any additions of fields, then create a blank migration in the middle to add your data migration to, then do another removal of fields. This way, in the middle migration, you have access to both the fields you are moving data from and the fields you're moving it to. |
| | 116 | |
| | 117 | You can have a look at the 0003 and 0005 migrations if you wish, but they're reasonably standard schema migrations. We're interested in `0004_migrate_names.py` - open it up, and you should see this: |
| | 118 | |
| | 119 | {{{ |
| | 120 | #!python |
| | 121 | from south.db import db |
| | 122 | from django.db import models |
| | 123 | from southdemo.models import * |
| | 124 | |
| | 125 | class Migration: |
| | 126 | |
| | 127 | def forwards(self, orm): |
| | 128 | "Write your forwards migration here" |
| | 129 | |
| | 130 | |
| | 131 | def backwards(self, orm): |
| | 132 | "Write your backwards migration here" |
| | 133 | |
| | 134 | |
| | 135 | models = { |
| | 136 | ... cut for clarity ... |
| | 137 | } |
| | 138 | |
| | 139 | complete_apps = ['southdemo'] |
| | 140 | }}} |
| | 141 | |
| | 142 | When you run `./manage.py startmigration` with only an app name and a migration name, South will create a skeleton template of a migration for you to fill in - it's much more useful than doing that part yourself. |
| | 143 | |
| | 144 | Here, we're interested in data migrations, and so we'll be using the ORM. One thing you should note is that the ORM will '''not work during a dry run''' - if you're using MySQL, all migrations are dry-run before each application, and if you're on another database, you should code to make sure your migrations are portable. You have two ways of making ORM code not run during a dry run: |
| | 145 | |
| | 146 | * Wrapping the ORM code in an `if not db.dry_run:` block |
| | 147 | * Adding the `no_dry_run = True` statement to the Migration class |
| | 148 | |
| | 149 | We'll do the latter, since our entire migration will be using the ORM, and in general you should be making migrations this way anyway. Adding it to the class, we get this: |
| | 150 | |
| | 151 | {{{ |
| | 152 | #!python |
| | 153 | from south.db import db |
| | 154 | from django.db import models |
| | 155 | from southdemo.models import * |
| | 156 | |
| | 157 | class Migration: |
| | 158 | |
| | 159 | no_dry_run = True |
| | 160 | |
| | 161 | def forwards(self, orm): |
| | 162 | "Write your forwards migration here" |
| | 163 | ... |
| | 164 | }}} |
| | 165 | |
| | 166 | Now, we can start writing our migration. You use the fake ORM just like the normal ORM, but prefixing all models with `orm.`. Thus, our loop to copy the names across might look something like this: |
| | 167 | |
| | 168 | TBC |