Django - How to rename a model field using South?
我想更改模型中特定字段的名称:
1 2 3
| class Foo(models.Model):
name = models.CharField()
rel = models.ForeignKey(Bar) |
应改为:
1 2 3
| class Foo(models.Model):
full_name = models.CharField()
odd_relation = models.ForeignKey(Bar) |
号
使用South最简单的方法是什么?
- 另请参阅stackoverflow.com/questions/2862979/…,以重命名模型而不是模型字段。
您可以使用db.rename_column函数。
1 2 3 4 5 6 7 8 9 10 11 12
| 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') |
db.rename_column的第一个参数是表名,因此请记住django是如何创建表名的:
Django automatically derives the name of the database table from the name of your model class and the app that contains it. A model's database table name is constructed by joining the model's"app label" -- the name you used in manage.py startapp -- to the model's class name, with an underscore between them.
号
如果您有多个单词、驼色大小写的模型名称,例如projectitem,则表名将为app_projectitem(即,即使是驼色大小写的,也不会在project和item之间插入下划线)。
- 这对名称全名有效,但对关系字段无效,对吗?
- 我尝试了db.rename_column("app_foo"、"rel"、"odd_relation"),并收到了:_my sql_exceptions.operationalerror:(1025,"重命名时出错"。\ap_site sql-1034_20"到"。\my_app_db\app_foo"(errno:150)")
- 结果发现,此错误是因为有索引绑定此列(Django生成了唯一的u together约束)。你知道怎么从这里继续吗?
- 不会——自动拿起这个吗?
- 重要提示:如果要使用此名称,请确保"app-foo"是数据库表名,例如:"mainapp-profile","name"是数据库的旧列名(不是模型字段名),例如:"user-id"和"full-name"将是希望列具有的新名称(同样,是数据库列,而不是字段名)。所以:db.rename_column(‘mainapp_profile’、‘user_id’、‘new_user_id’)同样,如果您处理的是外键,则在重命名时应该在其中包含"_id"部分。
- 如果手动执行此db.rename_列,则可能需要在之后执行假架构迁移以清除备份内容。这是首先通过重命名列来迁移更改。然后修复模型(更新名称),然后执行./manage.py schemaMigration app--auto&;&;/manage.py migrate app--fake。
- 您还可以使用./manage.py schemaMigration my_app renaming_column_x--empty创建一个空迁移,并将代码放在其中。
- @戴夫:不,这不是南方支持的自动检测。我刚在South 0.7.3上测试过,South认为旧的列名已经被删除,新的列名已经被删除。
- south.aeracode.org/ticket/158重命名后编辑dict的有趣评论
- 注意:如果重命名的表是唯一的together关系的一部分,则必须用db.create_unique重新声明它。
- --空并没有多大帮助,而是使用--auto和modify创建的迁移。这样,它就不会声明字段已被删除,以便下次迁移models.py。
- 可以在DataMigration中检索对应于模型的db表,并在其中重命名列。
我要做的是:
在您的模型中更改列名(在本例中是myapp/models.py)
运行./manage.py schemamigration myapp renaming_column_x --auto。
注:renaming_column_x可以是您喜欢的任何东西,它只是为迁移文件提供描述性名称的一种方法。
这将生成一个名为myapp/migrations/000x_renaming_column_x.py的文件,该文件将删除旧列并添加新列。
修改此文件中的代码以将迁移行为更改为简单的重命名:
1 2 3 4 5 6 7 8 9
| 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') |
号
- 您的命令中列的名称是什么?x还是column_x?
- 您所引用的命令的一部分只是用来命名迁移,它可以是您喜欢的任何类型。编辑列名时,需要在迁移文件中指定该列名。
- 首先创建--auto迁移是一个很好的技巧。它避免了南方ORM冷冻库的问题,如果迁移只使用forwards和backwards方法,而不包含冻结的model对象,则会发生这种问题。
- 如何回答South的问题"既然要删除此字段,必须指定默认值"?
- 可能值得为此提出一个新问题,因为列类型很重要,可能还需要其他上下文信息来正确选择默认值。
- 我在这个方法中遇到的一个问题是,db.rename_column不重命名与列关联的约束。迁移仍将有效,但您将使用以旧列名命名的约束。我有一个带有唯一性约束的列,用这个方法重命名了它,测试了唯一性约束是否仍然存在,并得到了一个错误,但是约束本身的名称仍然使用旧的列名称。也许一个明确的db.delete_unique和db.create_unique可以做到,但我决定采用sjh的解决方案。
我不知道db.rename列,这听起来很方便,但是在过去,我添加了新列作为一个架构迁移,然后创建了一个数据迁移以将值移动到新字段,然后再创建第二个架构迁移以删除旧列。
- 我也是。模式数据模式技术的问题在于,您的字段/模型的名称不同。有时,如果您使用规范名称来启用调度程序,这是一个问题…
- 我刚试过这个,但没用,因为有名字冲突。我有完全相同的FK,但不同的名字。它没有验证。所以,不要这样做。
- @乔纳森,他想要不同的名字!…@朝圣者,要不要贴些密码?这个星期我已经做了好几次了,如果你的模型没有被验证,那么South就不会创建迁移。
- 这是可行的,但可能比其他人建议的"重命名栏"慢。我知道MySQL可以做一个"改变表…很快重命名列(或它是什么)。
- @Rory db.rename_column不会为您重命名约束,因此您必须手动处理。如果您忘记了这样做,迁移将起作用,除非您不知道可能还有一个约束仍在使用旧的列名。我不清楚这个问题是否仅仅是表面化的,或者在未来的移民中,限制是否应该被操纵,或是被南方抛弃,是否能够找到它。无论如何,像SJH建议的那样在这里做是一种安全的方法:你可以让South弄清楚它应该知道什么。
Django1.7引入了迁移,所以现在您甚至不需要安装额外的包来管理迁移。
要重命名模型,需要先创建空迁移:
1
| $ manage.py makemigrations --empty |
然后您需要像这样编辑迁移的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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'
),
] |
。
然后你需要跑:
只需更改模型并在1.9中运行makemigrations。
Django自动检测到您已删除并创建了单个字段,并询问:
1
| Did you rename model.old to model.new (a IntegerField)? [y/N] |
。
如果选择"是",则会创建正确的迁移。魔术。
将south添加到项目设置文件中已安装的应用程序中。
注释添加/修改的字段/表。
埃多克斯1〔10〕
江户十一〔11〕。
取消对字段的注释并写入修改后的字段
埃多克斯1〔12〕
埃多克斯1〔13〕
如果您使用的是"pycharm",那么您可以使用"ctrl+shift+r"而不是"manage.py",以及"shift"作为参数。