用Django和South重命名应用程序

Tre*_*ner 32 migration django rename django-south

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

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

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

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

luc*_*luc 44

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

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

python manage.py dumpdata old_app --natural --indent=4 1> old_app.json
Run Code Online (Sandbox Code Playgroud)

请注意--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()
Run Code Online (Sandbox Code Playgroud)

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

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

update django_content_type set app_label='new_app' where app_label='old_app'
Run Code Online (Sandbox Code Playgroud)

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

python manage.py loaddata old_app.json
Run Code Online (Sandbox Code Playgroud)

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

我希望它有所帮助

  • +1对于食谱.名称很重要:不应该仅仅因为难以重命名而重命名. (19认同)
  • 请注意,在Django 1.5之前,dumpdata会在转储之前加载内存中的所有内容,因此除非您的应用程序存储少量数据(这在Django 1.5中已修复),否则此解决方案将无法工作:您可能希望在答案中包含此警告.此外,我只是完成了所有步骤,只需稍作修改即可正常工作:请替换"[...]删除所有南迁移并重新生成新应用的初始迁移." 通过"[...]删除所有南迁移,重新生成并为新应用程序应用初始迁移.然后运行"update django_content_type set app_label ='new_app',其中app_label ='old_app'" (3认同)
  • 不知道为什么"不"是这里接受的答案.我有一个应用程序要重命名,它不是为了咯咯笑......与另一个应用程序存在冲突,Django/South不能很好地处理名称冲突. (2认同)

vdb*_*oor 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.
Run Code Online (Sandbox Code Playgroud)

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

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

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


jam*_*man 8

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

  • 此外,我认为必须将其重命名为00xx_rename_table_migration.py并将其放在my_app/migrations中,其中xx =迁移次数+ 1,以便我可以简单地将其用作:"./ manage.py migrate my_app"和". /manage.py迁移my_app(00xx -1)"回滚.如果要以不同的方式使用,请纠正我. (3认同)