Changes between Version 8 and Version 9 of Tutorial


Ignore:
Timestamp:
01/16/11 09:48:10 (4 years ago)
Author:
andrew
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Tutorial

    v8 v9  
    1  
    2 '''Note: This tutorial is out of date. Please read the [wiki:Tutorial1 new tutorial] instead.''' 
    3  
    4 = South tutorial = 
    5  
    6 == Introduction == 
    7  
    8 Welcome to the South tutorial! This is a brief guide to help you understand what South is about, and how to use it; if you ever want more documentation, have a look in the docs/ directory inside South. 
    9 Installation 
    10  
    11 First, go into the directory you'd like to install south in (I personally use /home/andrew/Programs/), and check out the code from subversion: 
    12  
    13 {{{ 
    14 svn co https://svn.aeracode.org/svn/south/trunk south 
    15 }}} 
    16  
    17 Then, you'll need to link this directory into your python path; on OSX or Linux systems, this is usually 
    18  
    19 {{{ 
    20 ln -s `pwd`/south SITE-PACKAGES-DIR/south 
    21 }}} 
    22  
    23 where SITE-PACKAGES-DIR is the directory described in the "Where are my site-packages stored?" part of the Django documentation. 
    24  
    25 Finally, go to the project you want to use South in, and add 'south' to the INSTALLED_APPS setting in settings.py. Then, run ./manage.py syncdb. 
    26  
    27 == The new syncdb == 
    28  
    29 When you run syncdb as I suggest above, you'll notice that it's changed looks. This is because you're now running South's syncdb rather than the normal Django one; our one examines your apps to find out which ones use migrations and which don't, and then only runs syncdb on the ones without migrations. An app is said to 'have migrations' if it has a module called 'migrations' inside it; South will create that for you when you ask to start your first migration on an app without migrations. 
    30  
    31 == your first migration == 
    32  
    33 It's time to go ahead and start creating migrations. So let's do just that; South has a command to do all the dirty work for us. Take an app you have lying around (or create a new one, and add it to INSTALLED_APPS), and in the project directory run: 
    34  
    35 {{{ 
    36 ./manage.py startmigration app_name my_first_migration 
    37 }}} 
    38  
    39 That will create the migrations module inside the app 'app_name' and create a blank migration inside it for you called 0001_my_first_migration.py. Open this file, and you'll see something like the following: 
    40  
    41 {{{ 
    42 #!python 
    43 from south.db import db 
    44 from public_site.models import * 
    45  
    46 class Migration: 
    47      
    48     def forwards(self): 
    49         "Write your forwards migration here" 
    50      
    51     def backwards(self): 
    52         "Write your backwards migration here" 
    53 }}} 
    54  
    55 The methods 'forwards' and 'backwards' will get called when you apply the migration and roll it back, respectively. All your migration code goes in here; for now, let's just make them print out what they're doing: 
    56  
    57 {{{ 
    58 #!python 
    59 from south.db import db 
    60 from public_site.models import * 
    61  
    62 class Migration: 
    63      
    64     def forwards(self): 
    65         print "FORWARD! Hop to it." 
    66      
    67     def backwards(self): 
    68         print "RUN AWAY!!!" 
    69 }}} 
    70  
    71 Now, let's try running our migrations: 
    72  
    73 {{{ 
    74 ./manage.py migrate app_name 
    75 }}} 
    76  
    77 You should get some output which shows you that South has detected your app is at migration #0, that it wants to be at #1, and then it will apply the migration (and you'll see your method print 'FORWARD...' in the midst of all this). 
    78  
    79 Let's try rolling it back; you can tell South to roll forwards or backwards to any migration by specifying the migration you should end up just afterwards. Since we want to go back past the first migration, we use the special name 'zero' to roll back all changes: 
    80  
    81 {{{ 
    82 ./manage.py migrate app_name zero 
    83 }}} 
    84  
    85 See? It's undone the migration, and you'll have got 'RUN AWAY!!!' printed. Now it's time to do something useful with these migrations. 
    86  
    87  
    88 == Automatic Migrations == 
    89  
    90 At this point, we'll need a model of some kind in your app's models.py; we suggest you go and make one. Something like this will do: 
    91  
    92 {{{ 
    93 #!python 
    94 class Spam(models.Model): 
    95     weight = models.FloatField() 
    96     expires = models.DateTimeField() 
    97     name = models.CharField(max_length=255) 
    98 }}} 
    99  
    100 Now, we could sit down and write a migration by hand that would create this table in forwards() and delete it in backwards(). However, we don't like lots of work, so instead South will do it for us: 
    101  
    102 {{{ 
    103 ./manage.py startmigration app_name create_spam --model Spam 
    104 }}} 
    105  
    106 That tells it to create a migration called create_spam, in the app app_name, and autogenerate it from the model Spam. You'll get something like this: 
    107  
    108 {{{ 
    109 #!python 
    110  
    111 from south.db import db 
    112 from app_name.models import * 
    113  
    114 class Migration: 
    115      
    116     def forwards(self): 
    117          
    118         # Model 'Spam' 
    119         db.create_table("app_name_spam", ( 
    120             ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), 
    121             ('weight', models.FloatField()), 
    122             ('expires', models.DateTimeField()), 
    123             ('name', models.CharField(max_length=255)) 
    124         )) 
    125          
    126         db.send_create_signal('app_name', ['Spam']) 
    127      
    128     def backwards(self): 
    129          
    130         db.delete_table("aeblog_spam") 
    131  
    132 }}} 
    133  
    134 See how it's autodetected the model, and made the migration for us? Isn't that helpful? 
    135  
    136 == Columns, Columns, Everywhere! == 
    137  
    138 Of course, most of your work won't be adding new tables, but rather new columns. As of version 0.4/revision [109], South has an `--add-field` option to `./manage.py startmigration`. 
    139  
    140 Like the `--model` example above, you call startmigration with an app and migration name: 
    141  
    142 {{{ 
    143 ./manage.py startmigration app_name add_foo --add-field MyModel.foo 
    144 }}} 
    145  
    146 Note that you must provide the field name as `ModelName.field_name`, since South won't know what model you want otherwise! You should also have already written that column's definition in models.py. 
    147  
    148 As with --model, you can use --add-field many times in a single call if you want to add a lot of columns: 
    149  
    150 {{{ 
    151 ./manage.py startmigration mitest some_cols --add-field user.age --add-field user.profile --add-field post.user 
    152 }}} 
    153  
    154 (also note here that you're free to write the model class names in lowercase; they're actually stored that way in Django) 
    155  
    156 == All In One == 
    157  
    158 However, that's not quite good enough yet. Now syncdb doesn't work, how are you going to create all the tables when you've just written your new models.py? 
    159  
    160 One answer is to use multiple `--model` switches on createmigration - it will create a migration that makes multiple tables at once: 
    161  
    162 {{{ 
    163 ./manage.py startmigration app_name create_spam --model Spam --model Eggs 
    164 }}} 
    165  
    166 However, there's a handy shortcut for creating a migration containing creation definitions for all the models: 
    167  
    168 {{{ 
    169 ./manage.py startmigration app_name --initial 
    170 }}} 
    171  
    172 == Words of Warning == 
    173  
    174 If you follow the commands above in order, exactly, you'll end up with a whole mess of migrations. If you use --initial, it must be the first migration; otherwise, two migrations will try to make the same table and you'll get an error. 
    175  
    176 Similarly, please realise createmigration is only for creating migrations for new models in your schema; if you've added a field to a model, running it won't create a migration that will upgrade your current table (you need to write that yourself); it will instead create a migration that will attempt to recreate the model's table with its new fields. This will fail. 
    177  
    178 Migrations are very simple, at their heart; they simply manipulate the database, and they must do it in a way so that running through them all from beginning to end results in a current version of the database schema. Our tools aim to make this job easier, but they're no replacement for understanding exactly what is going on. 
    179  
    180 == End of the Line == 
    181  
    182 This tutorial needs more work; if you feel like adding something, please do! 
    183  
    184 Some things you might want to try: 
    185  
    186  * Adding a new migration with the wrong number - e.g. another 0002 migration when you already have a 0003 (just rename a 0004 if you use createmigration and it makes one). The resulting problem, and the resolutions, are discussed in [wiki:CommandReference#ConflictResolution the command reference]. 
     1Please see http://south.aeracode.org/docs/