32

我正在将应用程序重命名为更合适的名称。在这样做时,我想确保South正确迁移数据库(重命名数据库表并更改 django_content_type 或 south_migrationhistory 中的引用)。我知道如何将模型迁移到其他应用程序,但是当我尝试重命名应用程序本身时,South 无法正确识别迁移历史记录。

不受欢迎的解决方案:在重命名old_app时,new_app我可以old_app/migrations保持原样并将新的迁移添加到此目录以迁移数据库以引用new_app

如果可能的话,我宁愿old_app完全删除该目录。我还没有想到更好的解决这个问题的方法。

在不丢失数据的情况下使用 Django South 重命名应用程序的最佳方法是什么?

4

6 回答 6

45

我同意 Laksham 的观点,即您应该避免这种情况。但有时,我们必须这样做。我过去曾遇到过这种情况,并且以这种方式进行了管理。

如果您想避免丢失数据,可以将旧的应用程序数据转储到 json 文件中。

python manage.py dumpdata old_app --natural --indent=4 1> old_app.json

请注意 --natural 选项将强制使用其自然键 (app_name, model) 导出内容类型

然后你可以创建一个小命令来打开这个 json 文件并将所有 old_app 引用替换为 new_app。

像这样的东西应该工作

class Command(BaseCommand):
    help = u"Rename app in json dump"

    def handle(self, *args, **options):
        try:
            old_app = args[0]
            new_app = args[1]
            filename = args[2]
        except IndexError:
            print u'usage :', __name__.split('.')[-1], 'old_app new_app dumpfile.json'
            return

        try:
            dump_file = open(filename, 'r')
        except IOError:
            print filename, u"doesn't exist"
            return

        objects = json.loads(dump_file.read())
        dump_file.close()

        for obj in objects:
            obj["model"] = obj["model"].replace(old_app, new_app, 1)

            if obj["fields"].has_key("content_type") and (old_app == obj["fields"]["content_type"][0]):
                obj["fields"]["content_type"][0] = new_app

        dump_file = open(filename, 'w')
        dump_file.write(json.dumps(objects, indent=4))
        dump_file.close()

然后重命名应用程序,在 INSTALLED_APPS 中更改名称。

然后,您应该删除所有南迁移,重新生成并为新应用程序应用初始迁移。然后运行 ​​SQL 命令:

update django_content_type set app_label='new_app' where app_label='old_app'

然后为新应用程序启动南迁移,以创建表并加载 json 文件。

python manage.py loaddata old_app.json

我在一个项目上做过类似的事情,它似乎工作正常。

我希望它有帮助

于 2011-09-14T13:45:39.227 回答
24

可以重命名应用程序。作为示例项目,请参见:

https://github.com/ASKBOT/django-south-app-rename-example

基本上,有 2 个迁移。首先使用 a 重命名表db.rename_table(),然后更新内容类型。这可以通过检查if not db.dry_run:. 请参阅如何将模型从一个 django 应用程序迁移到一个新应用程序?举个例子。

对于初始迁移,您可以直接重命名现有表(如果存在):

if 'old_app_table_name' in connection.introspection.table_names():
    db.rename_table('old_app_table_name', 'new_app_table_name')
else:
    # Create new app tables directly.

对于具有更多迁移的表,您可能需要检查是否已应用旧迁移名称:

from south.models import MigrationHistory
if MigrationHistory.objects.exists(app_name='old_app', migration='0001_initial'):
    return

最后,我建议使用 IDE(例如 PyCharm 试用版)重命名包(右键单击,重构 -> 在包上重命名),因为它会为您更新整个应用程序的所有用法,包括 URLconf、设置和导入。

于 2012-05-31T09:31:45.283 回答
8

在一些插电之后,我想出了这个。应该照顾它。 https://gist.github.com/jamesmfriedman/6168003

于 2013-08-06T20:01:24.210 回答
2

免责声明:这可能不是理想的方法,但这绝对比其他地方/之前建议的许多其他方法更容易。

如果您使用的是 PyCharm,您可以尝试以下解决方案。

  • 右键单击 Django 项目中的应用程序目录
  • Refactor> Rename> 输入新应用名称 ( new_app)
  • 检查Search for referencesSearch in comments and strings, 范围Project Files>Refactor
  • 这将向您显示文件将被重命名的位置 >Refactor
  • 如果您对项目名称不满意,您也可以对项目名称执行相同操作

现在问题来了。

python manage.py makemigrations

python manage.py migrate

这会做什么?

  • 这基本上会创建一个新应用程序并将所有迁移应用到这个新应用程序
  • 但是,您的数据仍驻留在旧应用程序中 ( old_app)
  • 我们需要把它带到new_app桌子上

在您的数据库中,我们需要

  1. new_app通过从表中复制数据将数据插入old_app表中

INSERT INTO new_app_table_name SELECT * FROM old_app_table_name;

您必须对应用程序中的所有模型/表格执行此操作

  1. 重置表的顺序以避免在django中出现主键冲突错误

SELECT setval('new_app_table_name_id_seq', (SELECT MAX(id) FROM new_app_table_name));

您必须对步骤 1 中的所有表执行此操作。

我不想无知,并声称它应该像这样容易。我的项目和模型结构相当复杂,但这对我来说很有吸引力。但是,如果您的项目结构过于复杂,则只有其中的一部分可能对您有用。

计算机科学中只有两个难点:缓存失效和命名。

——菲尔·卡尔顿

于 2020-06-21T03:16:46.357 回答
1

免责声明:这个答案适用于那些不关心迁移历史并且已经通过重命名应用程序而搞砸的人,完全忘记了迁移(就像我一样)。为我工作。

更改文件夹名称,处理代码中的所有导入并更改 settings.INSTALLED_APPS 中相应的应用程序名称后,只需删除所有以前的迁移文件夹。然后像这样做一个初始的

manage.py schemamigration new_app --initial

然后,在应用它时,像这样伪造它

manage.py migrate new_app 0001 --fake

不要忘记 --fake 它,否则您可能最终会丢失数据

所有进一步的迁移都可以正常工作

manage.py migrate new_app 0002

您也可以从 south_migrationhistory 中删除 app_name = "old_app"

于 2016-04-05T15:21:05.157 回答
-6

我不会弄乱应用程序名称。您在任何地方都引用应用程序名称。URL confs、设置、其他应用程序、模板等。

django 的设计方式,相应地向南,假设不需要更改应用程序名称。- 为您的项目命名您想要的名称。你在任何地方都没有提到它。更改应用名称很麻烦。如果您真的想重命名您的应用程序,您不需要的解决方案是我看到的最佳解决方案。

对于它的价值,import as如果您愿意,您可以随时使用 python 以不同的名称导入应用程序。

于 2010-12-31T06:43:44.520 回答