Django 将现有字段更改为外键
Django change an existing field to foreign key
我曾经有过这样的模型:
class Car(models.Model):
manufacturer_id = models.IntegerField()
id
字段引用了另一个模型 Manufacturer
。但是,我意识到使用 django 的内置外键功能会很有用,所以我将模型更改为:
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer)
这实际上立即可以正常工作,查询工作没有错误,一切都很好,除了如果我尝试 运行 迁移,Django 输出以下内容:
- Remove field manufacturer_id from car
- Add field manufacturer to car
执行此迁移会清除数据库中的所有现有关系,所以我不想这样做。我真的根本不想要任何迁移,因为像 Car.objects.get(manufacturer__name="Toyota")
这样的查询工作正常。我想要一个适当的数据库外键约束,但它不是一个高优先级。
所以我的问题是:有没有办法进行迁移或其他允许我将现有字段转换为外键的方法?我无法使用 --fake
,因为我需要在开发人员、生产人员和同事的计算机上可靠地工作。
可以进行数据迁移
- 添加新字段
- 进行数据迁移https://docs.djangoproject.com/en/3.1/topics/migrations/#data-migrations
- 删除旧字段
我不确定,可能还有另一种解决方案,您可以将字段重命名为您想要的名称,然后将字段更改为新类型(进行迁移)
operations = [
migrations.RenameField(
model_name='car',
old_name='manufacturer_id',
new_name='manufacturer',
),
migrations.AlterField(
model_name='car',
name='manufacturer',
field=ForeignKey(blank=True, null=True,
on_delete=django.db.models.deletion.CASCADE
),
]
我今天遇到了同样的问题。
无需重命名现有字段或删除现有列即可完成。
- 使用 CreateModel 操作更新初始迁移
...
migrations.CreateModel(
name="Car",
fields=[
(
"manufacturer",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
db_constraint=False,
db_index=False,
to="Manufacturer",
),
),
- 检查
db_constraint
和 db_index
在 Car
模型的 Car.manufacturer
字段上是否为 True
。如果未设置字段,则为默认值。
- 运行
./manage.py makemigrations
生成 AlterField
具有所需约束和索引的迁移 Car.manufacturer_id
。
第一步不会影响数据库一致性,因为生成的 DDL 对于 IntegerField
和 ForeignKey
与 db_constaint=False
和 db_index=False
是相同的
第二次迁移添加了缺失的约束和索引。
您可以使用 ./manage.py sqlmigrate app migration
命令检查
我曾经有过这样的模型:
class Car(models.Model):
manufacturer_id = models.IntegerField()
id
字段引用了另一个模型 Manufacturer
。但是,我意识到使用 django 的内置外键功能会很有用,所以我将模型更改为:
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer)
这实际上立即可以正常工作,查询工作没有错误,一切都很好,除了如果我尝试 运行 迁移,Django 输出以下内容:
- Remove field manufacturer_id from car
- Add field manufacturer to car
执行此迁移会清除数据库中的所有现有关系,所以我不想这样做。我真的根本不想要任何迁移,因为像 Car.objects.get(manufacturer__name="Toyota")
这样的查询工作正常。我想要一个适当的数据库外键约束,但它不是一个高优先级。
所以我的问题是:有没有办法进行迁移或其他允许我将现有字段转换为外键的方法?我无法使用 --fake
,因为我需要在开发人员、生产人员和同事的计算机上可靠地工作。
可以进行数据迁移
- 添加新字段
- 进行数据迁移https://docs.djangoproject.com/en/3.1/topics/migrations/#data-migrations
- 删除旧字段
我不确定,可能还有另一种解决方案,您可以将字段重命名为您想要的名称,然后将字段更改为新类型(进行迁移)
operations = [
migrations.RenameField(
model_name='car',
old_name='manufacturer_id',
new_name='manufacturer',
),
migrations.AlterField(
model_name='car',
name='manufacturer',
field=ForeignKey(blank=True, null=True,
on_delete=django.db.models.deletion.CASCADE
),
]
我今天遇到了同样的问题。 无需重命名现有字段或删除现有列即可完成。
- 使用 CreateModel 操作更新初始迁移
...
migrations.CreateModel(
name="Car",
fields=[
(
"manufacturer",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
db_constraint=False,
db_index=False,
to="Manufacturer",
),
),
- 检查
db_constraint
和db_index
在Car
模型的Car.manufacturer
字段上是否为True
。如果未设置字段,则为默认值。 - 运行
./manage.py makemigrations
生成AlterField
具有所需约束和索引的迁移Car.manufacturer_id
。
第一步不会影响数据库一致性,因为生成的 DDL 对于 IntegerField
和 ForeignKey
与 db_constaint=False
和 db_index=False
是相同的
第二次迁移添加了缺失的约束和索引。
您可以使用 ./manage.py sqlmigrate app migration
命令检查