Django - 如何使用South重命名模型字段?

Jon*_*han 208 python django django-models django-south

我想更改模型中特定字段的名称:

class Foo(models.Model):
    name = models.CharField()
    rel  = models.ForeignKey(Bar)
Run Code Online (Sandbox Code Playgroud)

应改为:

class Foo(models.Model):
    full_name     = models.CharField()
    odd_relation  = models.ForeignKey(Bar)
Run Code Online (Sandbox Code Playgroud)

使用南方最简单的方法是什么?

goo*_*orp 230

你可以使用这个db.rename_column功能.

class Migration:

    def forwards(self, orm):
        # Rename 'name' field to 'full_name'
        db.rename_column('app_foo', 'name', 'full_name')




    def backwards(self, orm):
        # Rename 'full_name' field to 'name'
        db.rename_column('app_foo', 'full_name', 'name')
Run Code Online (Sandbox Code Playgroud)

第一个参数db.rename_column是表名,所以记住Django如何创建表名是很重要的:

Django自动从模型类的名称和包含它的应用程序派生数据库表的名称.模型的数据库表名称是通过将模型的"app label"(您在manage.py startapp中使用的名称)连接到模型的类名称,并在它们之间加下划线来构建的.

如果你有一个多措辞,类似于驼峰的模型名称,例如ProjectItem,那么表名将是app_projectitem(即,不会在它们之间插入下划线project,item即使它们是驼峰式的).

  • 您还可以使用./manage.py schemamigration my_app renaming_column_x --empty来创建空迁移,只需将代码放入其中 (24认同)
  • 重要说明:如果您打算使用它,请确保"app_foo"是数据库表名,例如:"mainapp_profile","name"是数据库的旧列名(不是模型字段名称),例如:"user_id"和"full_name"将是您希望列具有的新名称(再次,数据库列而不是字段名称).所以:db.rename_column('mainapp_profile','user_id','new_user_id')另外,如果你正在处理外键,你在重命名时应该有"_id"部分. (23认同)
  • --empty没有多大帮助,而是使用--auto并修改创建的迁移.这样,对于models.py的下一次迁移,它将不会删除声明字段. (11认同)
  • 如果您手动执行此db.rename_column,则可能需要在进行虚假的模式迁移后进行清理.这是首先通过重命名列来迁移更改.然后修复模型(以获得更新的名称),然后执行./manage.py schemamigration app --auto && ./manage.py migrate app --fake). (3认同)
  • 这可以在name\full_name上工作,但不在关系字段上,对吗? (2认同)

don*_*ner 39

这是我做的:

  1. 在模型中更改列名称(在此示例中将是myapp/models.py)
  2. ./manage.py schemamigration myapp renaming_column_x --auto

注意renaming_column_x可以是您喜欢的任何内容,它只是为迁移文件提供描述性名称的一种方式.

这将生成一个名为的文件myapp/migrations/000x_renaming_column_x.py,该文件将删除旧列并添加新列.

修改此文件中的代码以将迁移行为更改为简单重命名:

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Renaming column 'mymodel.old_column_name' to 'mymodel.new_column_name'
        db.rename_column(u'myapp_mymodel', 'old_column_name', 'new_column_name')

    def backwards(self, orm):
        # Renaming column 'mymodel.new_column_name' to 'mymodel.old_column_name'
        db.rename_column(u'myapp_mymodel', 'new_column_name', 'old_column_name')
Run Code Online (Sandbox Code Playgroud)

  • 我对这个方法的一个问题是`db.rename_column`不重命名与列关联的*constraints*.迁移仍然有效,但您将拥有以旧列名命名的约束.我有一个具有唯一性约束的列,使用此方法重命名它,测试唯一性约束仍然存在并得到错误但约束的名称本身仍然使用旧列名称.也许一个明确的`db.delete_unique`和`db.create_unique`就可以了,但我决定采用sjh的解决方案. (3认同)
  • 首先创建`--auto`迁移是一个很好的提示.它避免了南ORM冰柜的问题,如果迁移只有`forward`和`backwards`方法,但不包含冻结的`model`对象,就会出现问题. (2认同)

sjh*_*sjh 15

我不知道db.rename列,听起来很方便,但是在过去我将新列添加为一个schemamigration,然后创建了一个数据迁移,将值移动到新字段,然后第二个schemamigration删除旧列

  • @jonathan,他想要不同的名字!... @pilgrim,小心贴出一些代码?本周我已经多次这样做了,如果你的模型没有验证那么南方就不会创建迁移. (2认同)

Dmi*_*lov 9

Django 1.7引入了迁移,所以现在您甚至不需要安装额外的软件包来管理迁移.

要重命名模型,您需要先创建空迁移:

$ manage.py makemigrations <app_name> --empty
Run Code Online (Sandbox Code Playgroud)

然后你需要编辑你的迁移代码,如下所示:

from django.db import models, migrations

class Migration(migrations.Migration):

dependencies = [
    ('yourapp', 'XXXX_your_previous_migration'),
]

operations = [
    migrations.RenameField(
        model_name='Foo',
        old_name='name',
        new_name='full_name'
    ),
    migrations.RenameField(
        model_name='Foo',
        old_name='rel',
        new_name='odd_relation'
    ),
]
Run Code Online (Sandbox Code Playgroud)

之后你需要运行:

$ manage.py migrate <app_name>
Run Code Online (Sandbox Code Playgroud)


Cir*_*四事件 5

只需更改模型并makemigrations在1.9中运行

Django会自动检测到您已删除并创建了一个字段,并询问:

Did you rename model.old to model.new (a IntegerField)? [y/N]
Run Code Online (Sandbox Code Playgroud)

说是,并且创建了正确的迁移.魔法.