[Django]-Is using multiple databases and South together possible?

9πŸ‘

My improved soultion:

To create the table south_migrationhistory in the other database:

./manage.py syncdb --database="my_db_name_for_apps"

You can now use a standard :

./manage.py migrate my_app

Here is my actual db_router.py

# -*- coding: UTF-8 -*-
apps =['app1', 'app2' ]    
db_name = 'my_db_name_for_apps'

class sh_router(object):
    """A router to control all database operations on models from applications in apps"""

    def db_for_read(self, model, **hints):
        """Point all operations on apps models to db_name"""
        if model._meta.app_label in apps :
            return db_name
        return None

    def db_for_write(self, model, **hints):
        """Point all operations on apps models to db_name"""
        if model._meta.app_label in apps:
            return db_name
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """Allow any relation if a model in apps is involved"""
        if obj1._meta.app_label in apps or obj2._meta.app_label in apps:
            return True
        return None

    def allow_syncdb(self, db, model):
        """Make sure the apps only appears on the db_name db"""
        if model._meta.app_label in ['south']:
            return True
        if db == db_name:
            return model._meta.app_label in apps
        elif model._meta.app_label in apps:
            return False
        return None

9πŸ‘

I found all the answers to be somewhat inaccurate, therefore, here is a summary.

First of all, everybody should of course read the very few lines about multiple databases in the South documentation πŸ™‚

The way to do this is to manually edit migration files to point to the correct database. The easiest way is to add this to the top of all files:

from south.db import dbs
db = dbs['name_of_you_nondefault_db']

The basic reason is that South does not pick up the name of the database from your database routers. This feature is simply not implemented and probably never will be with the coming of Django 1.7.

But to get things started, run:

python manage.py syncdb

Now, you have the south_migrationhistory table. Then to migrate your special database, do:

python manage.py migrate

The south_migrationhistory will NOT be created in every database, only the default one. So migration history can be kept centralized.

Multiple databases with different copies of the same application

In case you have multiple databases that you need to migrate the same application inside, you should not use a singular migration history.

Instead, create the south_migrationhistory like so:

python manage.py sql south | PGOPTIONS="-c search_path=NAME_OF_YOUR_SCHEMA_TO_CREATE_IN" python manage.py dbshell --database=name_of_you_nondefault_db

Now, you should run your migration specifying BOTH the app_label and the database to get the south_migrationhistory from.

python manage.py migrate name_of_app --database=name_of_you_nondefault_db
πŸ‘€benjaoming

5πŸ‘

In my db_router.py file I just uncomment the 'south' app in my apps list.
I launch a syncdb to create the table south_migrationhistory in the otherdb database.

./manage.py syncdb --database="otherdb"

And next comment again the 'south' app in my apps list.

You can now use a standard

./manage.py migrate my_app --database="otherdb"

Here is my db_router.py

#-*- coding: UTF-8 -*-

apps =['app1',
     'app2',
     'south', # <<<---------------- Comment / Uncomment here
   ]

db_name = 'otherdb'

class sh_router(object):
"""A router to control all database operations on models from applications in apps"""

  def db_for_read(self, model, **hints):
    """Point all operations on apps models to db_name"""
    if model._meta.app_label in apps :
        return db_name
    return None

  def db_for_write(self, model, **hints):
    """Point all operations on apps models to db_name"""
    if model._meta.app_label in apps:
        return db_name
    return None

  def allow_relation(self, obj1, obj2, **hints):
    """Allow any relation if a model in apps is involved"""
    if obj1._meta.app_label in apps or obj2._meta.app_label in apps:
        return True
    return None

  def allow_syncdb(self, db, model):
    """Make sure the apps only appears on the db_name db"""
    if db == db_name:
        return model._meta.app_label in apps
    elif model._meta.app_label in apps:
        return False
    return None

1πŸ‘

As Tomasz said, you have to syncdb your β€œgis” db too in order to create all the required tables, including south_migrationhistory.

./manage.py syncdb --database=gis
πŸ‘€Thomas Druez

1πŸ‘

Seems like Django 1.7 has allow_migrate() in its database router class to address this.

For earlier Djangos:

  • you need south_migrationhistory in any db where you want migrations
  • do a regular syncdb to put all the regular auth_* etc. tables in the default db
  • that will put south_migrationhistory in default
  • don’t do syncdb --database=other, that will duplicate all the auth_* etc.
    tables in other
  • instead, copy the south_migrationhistory table from default to other, e.g.

    sqlite3 main.sqlite ".sc south_migrationhistory" | sqlite3 other.sqlite

    or equivalent pg_dump command or whatever

  • then use migrate --database=other

At least this gets everything in the right place until you migrate to 1.7 πŸ™‚

πŸ‘€Terry Brown

0πŸ‘

I know the thread is old but I had the same problem and Google got me that thread.

So first you need to change the way you do your datamigration:

    def forwards(self, orm):
    "Write your forwards methods here."                               
        obj = orm.Obj()
        obj.name = 'my name'
        obj.save(using=db.db_alias)

The variable db.db_alias contain the name of the db to be used, so you will need to do everything with β€˜usgin’ and use db.db_alias as the db name.

then you run your migration with
./mange migrate App –database=DB_NAME

in case of schemamigration just directly use db.function like south does.

πŸ‘€MoiTux

-2πŸ‘

You probably want to have south_migrationhistory in both databases, so syncdb to β€œgist” for south app. Then your migration should go just fine.

Leave a comment