I'm adding South to an existing application which has many installations however I don't have access to production environments due to security reasons.
We can only supply Python installation script that will be run by persons that often don't have any knowledge about Django, South, etc.
I'm aware of the fact that for existing installations any future upgrade will have to start with executing:
manage.py syncdb
manage.py migrate --all 0001 --fake
and any new installations will start with:
manage.py syncdb
manage.py migrate -all
Is there any way to detect if south initial migrations were already applied (e.g. by detecting if south_migfationhistory table exists) in a database agnostic way (perhaps with Django itself) ?
What I would like to do is:
(pseudocode)
db = database.connect(dbname, user, password)
if db.table_existst('south_migrationhistory'):
execute 'manage.py syncdb'
execute 'manage.py migrate --all'
else:
execute 'manage.py syncdb'
execute 'manage.py migrate --all 0001 --fake'
execute 'manage.py migrate --all'
For future reference this is how I ended up doing this:
if args.settings_dir not in sys.path:
sys.path.append(args.settings_dir)
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
#try to query db for existing objects, e.g. user groups
#in order to detect if we are upgrading an existing installation
from django.db.utils import DatabaseError
try:
from django.contrib.auth.models import Group
tmp = len(Group.objects.all()) #evaluate to force db query
updating = True
except DatabaseError as e:
updating = False
#try to query db for South migrations in order to detect if South was already applied
#in this installation (if not then accessing MigrationHistory will throw an excepion)
try:
from south.models import MigrationHistory
has_south = bool(len(MigrationHistory.objects.all()))
except ImportError as e:
print 'ERROR: Error importing South migration history: ' + str(e)
print 'Exiting'
exit(1)
except DatabaseError as e:
has_south = False
#syncdb to create south_migrationhistory table, portal models will not be synced
from django.core.management import execute_from_command_line
argv = ['manage.py', 'syncdb', '--settings=settings', '--pythonpath=' + args.settings_dir]
execute_from_command_line(argv)
#if we are updating existing installation and South wasn't already applied
#then initial migration has to be 'faked' in order to sync with existing tables
if updating and not has_south:
print 'INFO: Faking initial database migration...'
argv = ['manage.py', 'migrate', '--all', '0001', '--fake',
'--settings=settings', '--pythonpath=' + args.settings_dir]
execute_from_command_line(argv)
#run normal migrations
print 'INFO: Applying database migrations...'
argv = ['manage.py', 'migrate', '--all',
'--settings=settings', '--pythonpath=' + args.settings_dir]
execute_from_command_line(argv)