I just recently started working with Django and I was almost immediately infuriated by the flawed syncdb command, which doesn’t really synchronize anything, can only create tables for new models.
And adding or deleting fields into existing models turns into a real pain in ass - you have to “peek” at how ORM would create tables again (manage.py sqlall) and manually create ALTER TABLE for changed columns of tables.
That is, the ORM in Django somehow implies active fucking with the SQL shell, because in the process of prototyping, these fields in the models change simply in batches.
')
Googling, I found several ways to automate changing the database schema and eventually settled on
South . This utility automates the db schema migration process. (and the name of the utility, as I understand it, beats the term “migration” - in the winter, all birds fly to yuh :)).
I chose South due to the fact that it stores the history of migrations and you can undo / redo, as well as adjust the migration code by hand.
You can read the full tutorial here:
south.aeracode.org/wiki/Tutorial , I’ll only briefly explain how it works.
Installation
1. Merge svn'om utility code from here:
https://svn.aeracode.org/svn/south/trunk2. Put it in python / lib / site-packages or somewhere else where it will be visible
3. In settings.INSTALLED_APPS add 'south'
4. Make the usual manage.py syncdb and see that it has become something else.
Using
Now imagine a situation: in the already existing model we need to add a couple of fields. For example, such:
class CompanyProduct (models.Model):
# .. -, - ..
download_url = models.URLField (
u ' ' ,
blank = True, null = True)
system_requirements = models.TextField (
u ' ' ,
blank = True, null = True)
* This source code was highlighted with Source Code Highlighter .
Create a migration:
python manage.py startmigration [__app] add_download_section
--add-field CompanyProduct.download_url
--add-field CompanyProduct.system_requirements
Creating __init__.py in '[path_to_app]\migrations'...
Created 0001_add_download_section.py.
We apply it:
python manage.py migrate [__app]
Running migrations for [__app]:
- Migrating forwards to 0001_add_download_section.
> [__app]: 0001_add_download_section
= ALTER TABLE "products" ADD COLUMN "download_url" varchar (200) NULL ; []
= ALTER TABLE "products" ADD COLUMN "system_requirements" text NULL ; []
- Loading initial data for [__app].
Driven by scientific curiosity, we look at what South generated at 0001_add_download_section.py:
from south.db import db
from django.db import models
from [__app].models import *
class Migration:
def forwards(self):
# Adding field 'CompanyProduct.download_url'
db.add_column( 'products' , 'download_url' ,
models.URLField (u ' ' , blank = True, null = True))
# Adding field 'CompanyProduct.system_requirements'
db.add_column( 'products' , 'system_requirements' ,
models.TextField (u ' ' , blank = True, null = True))
def backwards(self):
# Deleting field 'CompanyProduct.download_url'
db.delete_column( 'products' , 'download_url' )
# Deleting field 'CompanyProduct.system_requirements'
db.delete_column( 'products' , 'system_requirements' )
Shoal
In my case, the file had to add the output "# coding = utf-8" to the beginning of the migration script (see /south/management/commands/startmigration.py, line 290), otherwise it was filed due to unicode strings in it.