Django South - 有什么方法可以检测是否需要进行南迁移?

时间:2013-06-25 20:43:49

标签: django dvcs django-south

假设你正在开发一个Django项目,有少数人使用(例如)git。当您执行git pull时,您可能会进行一些南迁移,但您可能不会注意到(由于某种原因)。然后,当您继续开发时,您可能会遇到python异常,因为您没有进行迁移。现在有时可能需要一段时间才能发现你忘记了这一点,这很烦人。

因此,我想,南方检测不到你没有完成所有的迁移,只是抛出一个异常,如果是这样的话?

我想这可能是一个设置,如果你想在不进行迁移的情况下继续开发,你可以关闭它。

2 个答案:

答案 0 :(得分:3)

好的,这是我的方式。

我有一个包含3次迁移的应用south_test,即'python manage.py migrate --list'显示:

south_test
  (*) 0001_initial
  (*) 0002_auto__add_person
  ( ) 0003_auto__add_field_person_age

那是(不是太)魔法代码:

from south.models import MigrationHistory
from south.migration import Migrations

all_migrations = Migrations('south_test')
applied_migrations = MigrationHistory.objects.filter(app_name='south_test')

not_applied = list(set(all_migrations) - set([migration.get_migration() for migration in applied_migrations]))

现在您进行了not_applied次迁移。 也许鬼迁移有一些细节。

有关详细信息,请参阅南方的migrate命令。

希望这有帮助!

答案 1 :(得分:1)

好的,我制作了一些可以满足我想要的中间件。当您执行请求时,它会检查您尚未应用的迁移并引发异常。请务必仅在开发中使用此中间件!

您还可以在https://gist.github.com/gitaarik/5974176

上找到来源
from south import migration
from south.models import MigrationHistory


class SouthUnranMigrationCheck(object):

    def process_request(self, request):
        '''
        Checks if you ran all South migrations. If not, it will throw an
        exception (DidNotApplyAllMigrations).
        '''

        unapplied_migrations = self.unapplied_migrations()

        if len(unapplied_migrations) > 0:

            message = u'You haven\'t run the following migrations: {}'.format(
                u''.join(
                    [u'\n  "{}" in app "{}".'.format(name, app)
                    for name, app in unapplied_migrations]
                )
            )

            raise DidNotApplyAllMigrations(message)

    def unapplied_migrations(self):
        '''
        Returns a list of tuples of unapplied migrations. The tuples consist of
        a migration name and an app label.
        '''

        applied_migrations = self.applied_migrations()
        unapplied_migrations = []

        for app_migration_files in migration.all_migrations():

            for migration_file in app_migration_files:

                app_label = migration_file.app_label()
                migration_name = migration_file.name()

                if migration_name not in applied_migrations[app_label]:
                    unapplied_migrations.append((migration_name, app_label))

        return unapplied_migrations

    def applied_migrations(self):
        '''
        Returns a dictionary with the app name in the key, and a list of
        migrations in the value.
        '''

        applied_migrations = {}

        for applied_migration in MigrationHistory.objects.all():

            if applied_migration.app_name not in applied_migrations:
                applied_migrations[applied_migration.app_name] = []

            applied_migrations[applied_migration.app_name].append(
                applied_migration.migration)

        return applied_migrations


class DidNotApplyAllMigrations(Exception):
    '''
    Exception that indicates that you havent run all migrations.
    '''
    pass