そうですね、この非常に特殊な問題を経験したり、心配したりする人はそれほど多くないようです。私はあちこちでいくつかのことを試しました。また、いくつかの点を理解するのに役立つサウス メーリング リストからのサポートも得ました。
基本的に、私が実装したソリューションは次のとおりです。
South のschemamigration によって自動生成されたごく普通の移行ファイルがあります。しかし、add_columnとdelete_columnのテーブル名を に変更しましたschema.table_name
。スキーマは、マルチテナント ミドルウェアをインポートすることによって提供されます。
その後、移行は、スキーマがパブリックスキーマに対して実行されない場合にのみ適用されます。実際には、スタンドアロンで実行すること、またはデータベースとスキーマの kwargs のみを使用することを意図したものではなく、新しい django コマンドである移行ランナーから実行することを意図しています。
残念ながら、ランナーは、ミドルウェアを毎回通過するために、マイグレーションを外部で呼び出す必要があります。もう 1 つのトリックは、各テナントの移行後に南部の以前の状態に偽装するために、移行の以前の状態を取得する必要があることです。
ここに私のスニペットがあります:
from subprocess import call
import os
from django.core.management.base import BaseCommand
from south.models import MigrationHistory
from myapp.models import MyModel
class Command(BaseCommand):
def handle(self, *args, **options):
#the only allowed arg is the prefix version and it should have a length of 4 (i.e. 0002)
applied = MigrationHistory.objects.filter(app_name='myapp').latest('applied')
current_version = applied.migration[:4]
call_args = ['python', os.path.join('bin', 'manage.py'), 'migrate', 'myorderbird.app.backups']
if len(args) == 1 and len(args[0]) == 4:
call_args.append(args[0])
obje_call_args = None
for obje in MyModel.objects.all():
if obje.schema_exists:
# fake the migration of the previous venue back to the current version
if obje_call_args:
obje_call_args = obje_call_args[:4] + [current_version, '--fake'] + obje_call_args[len(obje_call_args)-3:]
call(obje_call_args)
# migrate the venue in the loop
obje_call_args = list(call_args)
obje_call_args.extend(['--database={}'.format(obje.db), '--schema={}'.format(obje.schema)])
call(venue_call_args)