首页 文章

用Django和South重命名应用程序

提问于
浏览
31

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

Undesirable solution :在将 old_app 重命名为 new_app 时,我可以完整保留 old_app/migrations 并将新迁移添加到此目录以将数据库迁移到引用 new_app .

如果可能的话,我宁愿完全删除目录 old_app . 我还没有想过更好地解决这个问题 .

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

5 回答

  • 24

    我同意Laksham你应该避免这种情况 . 但有时候,我们必须这样做 . 我过去曾遇到过这种情况而且我已经这样管理过了 .

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

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

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

    然后,您可以创建一个小命令来打开此json文件,并使用new_app替换所有old_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
    

    我在项目上做了类似的事情,似乎工作正常 .

    我希望它有所帮助

  • 42

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

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

    基本上,有2次迁移 . 首先使用 db.rename_table() 重命名表,然后更新内容类型 . 通过检查 if not db.dry_run: ,可以将其合并为一个迁移 . 有关示例,请参见How do I migrate a model out of one django app and into a new one? .

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

    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,设置和导入 .

  • 8

    经过一些堵塞,我想出了这个 . 应该好好照顾它 . https://gist.github.com/jamesmfriedman/6168003

  • 1

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

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

    manage.py schemamigration new_app --initial
    

    然后,在应用它时,假装它就像这样

    manage.py migrate new_app 0001 --fake
    

    Do not forget to --fake it, otherwise you might end up losing data

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

    manage.py migrate new_app 0002
    

    你也可以从south_migrationhistory删除app_name =“old_app”

  • -6

    我不会乱用应用程序名称 . 你可以随处参考应用名称 . 网址,设置,其他应用,模板等

    django的设计方式,相应地南方,假设不需要更改应用程序名称 . - 为您的项目命名您想要的 . 你没有在任何地方引用它 . 更改应用程序名称非常麻烦 . 如果您真的想重命名您的应用,那么您不受欢迎的解决方案是我看到的最佳解决方案 .

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

相关问题