3

我正在将 South 添加到具有许多安装的现有应用程序中,但是由于安全原因,我无法访问生产环境。
我们只能提供 Python 安装脚本,这些脚本将由通常不了解 Django、South 等的人运行。

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

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

并且任何新安装都将从以下内容开始:

manage.py syncdb
manage.py migrate -all


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

(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'
4

2 回答 2

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)
于 2013-01-17T10:43:32.237 回答
0

解决您的情况实际上是 South 的一张出色门票:

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

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

它已经开放了 3 年,虽然它已经实施了一段时间,但它正在等待合并。如果您想要此功能,请随时评论该问题 ;-)

于 2013-10-08T04:31:50.783 回答