[[PageOutline]] = Server setup = Deploying CMT with PostgreSQL, Apache and `mod_wsgi` is the recommended way to get it up and running. == Setup PostgreSQL database == If the database tables aren't generated yet, an initial setup based on the models is needed. You can synchronize the database with the models from the commandline, by issuing the following command: {{{ python /path/to/sara_cmt/sara_cmt/manage.py syncdb }}} The manage.py script is a project specific wrapper of [http://docs.djangoproject.com/en/dev/ref/django-admin/ django-admin.py], which is automaticaly created in each Django project. == Basic Apache configuration == Be sure to activate `mod_wsgi`, and define the `WSGIScriptAlias` in your Apache server configuration: {{{ WSGIScriptAlias / /path/to/sara_cmt/apache/django.wsgi }}} The first bit has to be the URL you want to be serving CMT at, and the second is the location of the WSGI-file in the CMT project directory. Any request below the given URL will be served using the application that's definined in the WSGI-file. = Changes in datamodel = Thanks to introspection by the South package, it's possible to dynamicly modify the datamodel. South will make migration-files for you, which are stored in their own directory, defined in the settings-file of CMT. == Initial migration == To make the initial migration: {{{ python manage.py schemamigration --initial }}} In case of the cluster application in CMT it should print output like: {{{ + Added model 'cluster.InterfaceType' + Added model 'cluster.HardwareSpecifications' ... + Added model 'cluster.WarrantyContract' + Added model 'cluster.Connection' + Added M2M 'cluster.Company.buildings' + Added M2M 'cluster.HardwareUnit.role' + Added unique_together for [firstname, lastname] on Connection. + Added unique_together for [rack, first_slot] on HardwareUnit. + Added unique_together for [address, floor, label] on Room. + Added unique_together for [address1, city] on Address. Created 0001_initial.py. }}} This results in an initial migration file, consisting of Python code which: * creates a database table based on each added model * set relationships between the tables, based on the datamodel * set constraints for the database tables 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: {{{ python manage.py migrate --fake }}} Its output confirms that the database is already in sync with the datamodel: {{{ Running migrations for cluster: - Nothing to migrate. }}} == Migrations on changes == Once the datamodel has been changed you have to generate a new migration, which should be runned to keep the database in sync. === Generate migration === A migration should be generated by issuing the following command: {{{ python manage schemamigration --auto }}} '''Example''' ''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'' {{{ python manage.py schemamigration cluster telephone --auto }}} ''which should give an output like'' {{{ + Added field 'cluster.telephonenumber.connection' - Deleted field 'cluster.connection.phone' - Deleted field 'cluster.connection.cellphone' Created 0002_telephone.py. }}} ''In this case a migration-file (called 0002_telephone.py) has been saved in the migration-directory.'' === Run migration === Run a migration to migrate the database to the most recent changes by issuing the command: {{{ python manage.py migrate }}} '''Example''' ''In case of the generated migration of the previous example, the command should look like'' {{{ python manage.py migrate cluster }}} ''which should give an output like'' {{{ Running migrations for cluster: - Migrating forwards to 0002_telephone. > cluster: 0002_telephone = ALTER TABLE "cluster_telephonenumber" ADD COLUMN "connection_id" integer NOT NULL; [] = DROP TABLE "cluster_connection_phone" CASCADE; [] = DROP TABLE "cluster_connection_cellphone" CASCADE; [] = ALTER TABLE "cluster_telephonenumber" ADD CONSTRAINT "connection_id_refs_id_1741ef3" FOREIGN KEY ("connection_id") REFERENCES "cluster_connection" ("id") DEFERRABLE INITIALLY DEFERRED; [] = CREATE INDEX "cluster_telephonenumber_connection_id" ON "cluster_telephonenumber" ("connection_id"); [] - Loading initial data for cluster. }}} ''As you can see there has been executed some SQL-statements, which reflect the changes in the datamodel.''