Changes between Initial Version and Version 1 of AlterModelOnSyncDB


Ignore:
Timestamp:
Feb 26, 2007, 10:46:08 AM (18 years ago)
Author:
yary h <nospam@…>
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AlterModelOnSyncDB

    v1 v1  
     1I have a situation where I want to modify each database table as it is created. The solution I created should work for PostgreSQL or any backend. In this particular case, my project is using a MySQL database, and requires transactions- that is, InnoDB storage. Alas, my hosting service defaults all tables to MyISAM, and I can't change that.
     2
     3The usual method is to create a custom sql file "app_model.sql" that alters the table. That gets tedious when one has dozens, or hundreds of models.
     4
     5Here's an 80% solution. Add code like the below to your app's {{{ __init__.py }}}:
     6
     7
     8{{{
     9# use a consistant MySQL storage type for all apps, all models
     10
     11from django.dispatch import dispatcher
     12from django.db.models import signals
     13
     14default_storage = 'InnoDB'
     15storage = { 'app_model_has_different_storage':'MyISAM'}
     16skip = set(('app_model_should_go_unchanged',))
     17
     18def modify_MySQL_storage(sender, app, created_models, verbosity, interactive):
     19    from django.db import connection
     20    cursor = connection.cursor()
     21
     22    for model in created_models:
     23        db_table=model._meta.db_table
     24        if db_table not in skip:
     25            skip.add(db_table)
     26            engine = storage.get(model._meta.db_table,default_storage)
     27            stmt = 'ALTER TABLE %s ENGINE=%s' % (db_table,engine)
     28            if verbosity > 1: print '  ',stmt
     29            cursor.execute(stmt)
     30
     31# Modify SQL storage after any app installs
     32dispatcher.connect(modify_MySQL_storage,signal=signals.post_syncdb)
     33}}}
     34
     35I call this an 80% solution because it won't touch the intermediary M2M tables. For that, we need a signal that fires on the creation of each database table, or lists all tables that were created, which doesn't exist.
     36
     37If most tables are InnoDB but you try setting one or a few to MyISAM using {{{storage}}}, MySQL may complain about foreign keys... rather than making that work, I found it simpler to add the table to {{{skip}}} and write out the alter statement the old way, with the raw sql in {{{app/sql/app_model.sql}}}.
     38
     39The code could be refined to only alter models in a particular app.
Back to Top