简体   繁体   English

Django 将现有字段更改为外键

[英]Django change an existing field to foreign key

I used to have a model like this:我曾经有一个像这样的 model:

class Car(models.Model):
    manufacturer_id = models.IntegerField()

There is another model Manufacturer that the id field refers to. id字段指的是另一个 model Manufacturer However, I realized that it would be useful to use django's built-in foreign key functionality, so I changed the model to this:但是,我意识到使用 django 的内置外键功能会很有用,所以我将 model 更改为:

class Car(models.Model):
    manufacturer = models.ForeignKey(Manufacturer)

This actually works fine immediately, queries work without errors, everything is great, except that if I try to run migrations, Django outputs the following:这实际上立即工作正常,查询工作没有错误,一切都很好,除了如果我尝试运行迁移,Django 输出以下内容:

 - Remove field manufacturer_id from car
 - Add field manufacturer to car

Doing this migration would clear all the existing relationships in the database, so I don't want to do that.进行此迁移会清除数据库中所有现有的关系,所以我不想这样做。 I don't really want any migrations at all, since queries like Car.objects.get(manufacturer__name="Toyota") work fine.我根本不想要任何迁移,因为像Car.objects.get(manufacturer__name="Toyota")这样的查询可以正常工作。 I would like a proper database foreign key constraint, but it's not a high priority.我想要一个适当的数据库外键约束,但这不是一个高优先级。

So my question is this: Is there a way to make a migration or something else that allows me to convert a existing field to a foreign key?所以我的问题是:有没有办法进行迁移或其他允许我将现有字段转换为外键的方法? I can't use --fake since I need to reliably work across dev, prod, and my coworkers computers.我不能使用--fake ,因为我需要可靠地跨开发、生产和我的同事计算机工作。

You can do data migration您可以进行数据迁移

  1. add new field添加新字段
  2. do a data migration https://docs.djangoproject.com/en/3.1/topics/migrations/#data-migrations进行数据迁移https://docs.djangoproject.com/en/3.1/topics/migrations/#data-migrations
  3. remove old field删除旧字段

I am not sure, there might be another solution where you can rename the field to name you want to, then alter the filed to new type (do a migration)我不确定,可能还有另一种解决方案,您可以将字段重命名为您想要的名称,然后将字段更改为新类型(进行迁移)

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
            ),
    ]

I've faced the same issue today.我今天也遇到了同样的问题。 Can be done without renaming an existing field or dropping existing column.无需重命名现有字段或删除现有列即可完成。

  1. Update the initial migration with CreateModel operation使用 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",
                    ),
                ),
  1. Check that db_constraint and db_index are True on Car.manufacturer field of Car model.检查Car model 的Car.manufacturer字段上的db_constraintdb_index是否为True True is a default value if the fields not set.如果未设置字段,则 True 是默认值。
  2. Run ./manage.py makemigrations that generates AlterField migration with required constraint and index on Car.manufacturer_id .运行./manage.py makemigrations生成AlterField迁移,并在Car.manufacturer_id上具有所需的约束和索引。

The first step won't effect db consistency because the generated DDL will be the same for IntegerField and ForeignKey with db_constaint=False and db_index=False and the second migration adds missing constraint and index.第一步不会影响 db 一致性,因为生成的 DDL 对于IntegerFieldForeignKey将是相同的,其中db_constaint=Falsedb_index=False并且第二次迁移添加了缺少的约束和索引。

You can check that with ./manage.py sqlmigrate app migration command您可以使用./manage.py sqlmigrate app migration命令进行检查

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM