2013-01-13 42 views
3

我将South添加到有许多安装的现有应用程序中,但由于安全原因,我无法访问生产环境。
我们只能提供Python安装脚本,这些脚本将由通常不具备任何有关Django,South等知识的人员运行。Django South:检测生产中是否应用了伪迁移

我知道,对于现有安装,任何未来升级都必须开始执行:

manage.py syncdb 
manage.py migrate --all 0001 --fake 

任何新安装都将开始:

manage.py syncdb 
manage.py migrate -all 


有什么办法,如果已经应用于南初始迁移检测(例如,通过检测是否存在south_migfationhistory表)以数据库不可知的方式(可能与Django本身)?
我想要做的是:

(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' 
+1

首先,始终运行--fake将打破..非常快。当您知道数据库已同步到特定迁移时,虚拟应只运行一次。所有未来的更新应该是一个简单的迁移。 是的,您应该通过'settings.INSTALLED_APPS'查询'south.models.MigrationHistory'来执行任何自定义逻辑。 –

+0

@Yuji是的,我的意思是在升级已有一些表格但尚未具备South的现有安装时,只应用一次'迁移 - 全部0001 - 构建'。在第一次升级之后,所有以下升级应该只能'迁移 - 全部'。这在我的伪代码示例中更具说明性。 – matf

回答

1

以供将来参考,这是我怎么会做这样的:

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) 
0

一个解决您的情况实际上是南方一个优秀票:

http://south.aeracode.org/ticket/430

票据建议创建一个标志--autofake-first,它将确定是否存在任何初始表,并且如果他们这样做,将假冒第一次迁移,但像往常一样运行其余的。如果您刚刚将应用程序转换为South,这很完美,但您需要将此更改作为远程或持续部署策略的一部分。

它已经开放了3年,虽然已经实施了一段时间,但它正在等待合并。随意对此事发表评论,如果你想这个功能;-)