| 32 | |
| 33 | |
| 34 | |
| 35 | = Changes in datamodel = |
| 36 | |
| 37 | Thanks to introspection by the South package, it's possible to dynamicly modify the datamodel. |
| 38 | South will make migration-files for you, which are stored in their own directory, defined in the settings-file of CMT. |
| 39 | |
| 40 | |
| 41 | == Initial migration == |
| 42 | |
| 43 | To make the initial migration: |
| 44 | |
| 45 | {{{ |
| 46 | python manage.py schemamigration <appname> --initial |
| 47 | }}} |
| 48 | |
| 49 | In case of the cluster application in CMT it should print output like: |
| 50 | |
| 51 | {{{ |
| 52 | + Added model 'cluster.InterfaceType' |
| 53 | + Added model 'cluster.HardwareSpecifications' |
| 54 | ... |
| 55 | + Added model 'cluster.WarrantyContract' |
| 56 | + Added model 'cluster.Connection' |
| 57 | + Added M2M 'cluster.Company.buildings' |
| 58 | + Added M2M 'cluster.HardwareUnit.role' |
| 59 | + Added unique_together for [firstname, lastname] on Connection. |
| 60 | + Added unique_together for [rack, first_slot] on HardwareUnit. |
| 61 | + Added unique_together for [address, floor, label] on Room. |
| 62 | + Added unique_together for [address1, city] on Address. |
| 63 | Created 0001_initial.py. |
| 64 | }}} |
| 65 | |
| 66 | This results in an initial migration file, consisting of Python code which: |
| 67 | * creates a database table based on each added model |
| 68 | * set relationships between the tables, based on the datamodel |
| 69 | * set constraints for the database tables |
| 70 | |
| 71 | Every time when a migration has been created it should be used to get the database tables synchronized. Because the initial migration is a diff from zero to the initial setup (which has already been done with the ./manage.py syncdb command), the migration has to be faked. To fake a migration: |
| 72 | |
| 73 | {{{ |
| 74 | python manage.py migrate <appname> --fake |
| 75 | }}} |
| 76 | |
| 77 | Its output confirms that the database is already in sync with the datamodel: |
| 78 | |
| 79 | {{{ |
| 80 | Running migrations for cluster: |
| 81 | - Nothing to migrate. |
| 82 | }}} |
| 83 | |
| 84 | |
| 85 | == Migrations on changes == |
| 86 | |
| 87 | Once the datamodel has been changed you have to generate a new migration, which should be runned to keep the database in sync. |
| 88 | |
| 89 | === Generate migration === |
| 90 | |
| 91 | A migration should be generated by issuing the following command: |
| 92 | {{{ |
| 93 | python manage schemamigration <appname> <migrationname> --auto |
| 94 | }}} |
| 95 | |
| 96 | '''Example''' |
| 97 | ''There was a model Connection with two fields that hold a telephonenumber, but those fields has been replaced by a foreign key in the table of the Telephone model; in that case the command could look like'' |
| 98 | {{{ |
| 99 | python manage.py schemamigration cluster telephone --auto |
| 100 | }}} |
| 101 | ''which should give an output like'' |
| 102 | {{{ |
| 103 | + Added field 'cluster.telephonenumber.connection' |
| 104 | - Deleted field 'cluster.connection.phone' |
| 105 | - Deleted field 'cluster.connection.cellphone' |
| 106 | Created 0002_telephone.py. |
| 107 | }}} |
| 108 | ''In this case a migration-file (called 0002_telephone.py) has been saved in the migration-directory.'' |
| 109 | |
| 110 | === Run migration === |
| 111 | |
| 112 | Run a migration to migrate the database to the most recent changes by issuing the command: |
| 113 | {{{ |
| 114 | python manage.py migrate <appname> |
| 115 | }}} |
| 116 | |
| 117 | '''Example''' |
| 118 | ''In case of the generated migration of the previous example, the command should look like'' |
| 119 | {{{ |
| 120 | python manage.py migrate cluster |
| 121 | }}} |
| 122 | ''which should give an output like'' |
| 123 | {{{ |
| 124 | Running migrations for cluster: |
| 125 | - Migrating forwards to 0002_telephone. |
| 126 | > cluster: 0002_telephone |
| 127 | = ALTER TABLE "cluster_telephonenumber" ADD COLUMN "connection_id" integer NOT NULL; [] |
| 128 | = DROP TABLE "cluster_connection_phone" CASCADE; [] |
| 129 | = DROP TABLE "cluster_connection_cellphone" CASCADE; [] |
| 130 | = ALTER TABLE "cluster_telephonenumber" ADD CONSTRAINT "connection_id_refs_id_1741ef3" FOREIGN KEY ("connection_id") REFERENCES "cluster_connection" ("id") DEFERRABLE INITIALLY DEFERRED; [] |
| 131 | = CREATE INDEX "cluster_telephonenumber_connection_id" ON "cluster_telephonenumber" ("connection_id"); [] |
| 132 | - Loading initial data for cluster. |
| 133 | }}} |
| 134 | ''As you can see there has been executed some SQL-statements, which reflect the changes in the datamodel.'' |