Django不断迁移相同的外键 [英] Django keeps migrating the same foreign key

查看:56
本文介绍了Django不断迁移相同的外键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将现有数据库导入到它自己的Django项目中.我已经通过 inspectdb 从数据库生成了初始模型,并且通过注释表元中的 managed = False 行,使Django能够一次控制每个表.设置.我从简单的模型开始,在启用带有外键的表时遇到了麻烦.Django不断为外键 DocTagID 生成相同的迁移,但我不确定为什么这样做?

I am importing an existing database into it's own Django project. I have generated the initial models from the database, via inspectdb, and am enabling Django to control each table one at a time by commenting the managed=False lines in the table meta settings. I've started with the simple models and am hitting a snag when enabling tables with foreign keys. Django keeps generating the same migration for the foreign key DocTagID and I'm not sure why it is doing so ?

有问题的表如下所示,所有内容都是由 inspectdb 生成的,除了注释行,这是我将表的控制权传递给Django的地方.

The table in question is shown below, everything is as generated by inspectdb with the exception of the commented line which is where I pass control of the table over to Django.

class Doctagversion(models.Model):
    id = models.IntegerField(db_column='Id', primary_key=True, blank=True)  # Field name made lowercase.
    doctagid = models.ForeignKey(DocTag, models.DO_NOTHING, db_column='DocTagId')  # Field name made lowercase.
    groupname = models.TextField(db_column='GroupName')  # Field name made lowercase.
    name = models.TextField(db_column='Name')  # Field name made lowercase.
    creationdate = models.DateTimeField(db_column='CreationDate')  # Field name made lowercase.
    lasteditdate = models.DateTimeField(db_column='LastEditDate', blank=True, null=True)  # Field name made lowercase.
    lastedituserid = models.IntegerField(db_column='LastEditUserId')  # Field name made lowercase.
    lastedituserdisplayname = models.TextField(db_column='LastEditUserDisplayName')  # Field name made lowercase.
    releasedate = models.DateTimeField(db_column='ReleaseDate', blank=True, null=True)  # Field name made lowercase.

    class Meta:
#         managed = False
        db_table = 'DocTagVersion'

在传递此控件之前,将使用 python -m manage.py makemigrations 生成该架构的初始迁移,并通过 python -m manage.py migration .该表的初始迁移如下, managed 最初设置为 False ,并且注释行是一个条目,我相信我应该添加此条目以告知Django外键(在生成的 models.py 中, inspectdb 的状态相同.

Before passing on this control an initial migration for the schema in question is generated using python -m manage.py makemigrations, and applied with python -m manage.py migrate. This initial migration for the table is as follows, managed is set to False initially and the commented line is an entry I believe I should add to inform Django of the foreign key (inspectdb states as much in the generated models.py).

    migrations.CreateModel(
        name='Doctagversion',
        fields=[
            ('id', models.IntegerField(blank=True, db_column='Id', primary_key=True, serialize=False)),
            # ('doctagid',models.ForeignKey(db_column='DocTagId', default=-1, on_delete=models.deletion.DO_NOTHING, to='DocTag')),
            ('groupname', models.TextField(db_column='GroupName')),
            ('name', models.TextField(db_column='Name')),
            ('creationdate', models.DateTimeField(db_column='CreationDate')),
            ('lasteditdate', models.DateTimeField(blank=True, db_column='LastEditDate', null=True)),
            ('lastedituserid', models.IntegerField(db_column='LastEditUserId')),
            ('lastedituserdisplayname', models.TextField(db_column='LastEditUserDisplayName')),
            ('releasedate', models.DateTimeField(blank=True, db_column='ReleaseDate', null=True)),
        ],
        options={
            'db_table': 'DocTagVersion',
            'managed': False,
        },
    ),

启用对表的控制后,第一次迁移只需更改表选项.

When I enable control over the table the first migration simply changes the table options.

    migrations.AlterModelOptions(
        name='doctagversion',
        options={},
    ),

如果初始迁移中不存在外键,则Django添加有问题的外键,如下所示.

Django adds the foreign key in question if it's not present in the initial migration as follows.

    migrations.AddField(
        model_name='doctagversion',
        name='doctagid',
        field=models.ForeignKey(db_column='DocTagId', default=-1, on_delete=django.db.models.deletion.DO_NOTHING, to='docutoo.DocTag'),
        preserve_default=False,
    ),

此后,它反复生成以下迁移,作为 python m manage.py makemigrations python -m manage.py migration 之间的一个循环.

Thereafter it repeatedly generates the following migration as one cycles between python m manage.py makemigrations and python -m manage.py migrate.

    migrations.AlterField(
        model_name='doctagversion',
        name='doctagid',
        field=models.ForeignKey(db_column='DocTagId', on_delete=django.db.models.deletion.DO_NOTHING, to='docutoo.DocTag'),
    ),

也许我的策略是错误的,我应该只在一次迁移中启用所有表?

Perhaps my strategy is wrong and I should simply enable all tables in one migration ?

据我所知,以下相关问题并不能说明我的情况:

As far as I can tell the following related question(s) do not account for my situation :

推荐答案

来自此错误报告似乎Django迁移对命名非常敏感,我在所有模型中均已注释掉 db_table .我相信我是在创建初始迁移后无意间破坏了后来的迁移.

From this Bug Report it seems Django migrations are quite sensitive to naming, I had commented out the db_table in all of my models. I believe I did this after creating the initial migration unwittingly breaking later ones.

  class Meta : 
    ...
#     db_table = "TableName"

因为我破坏了命名 makemigrations ,所以看不到表名已更改,因此最好通过重复声明该字段来解决该问题.

Because I broke the naming makemigrations could not see that the table name had changed and was doing it's best to resolve it by repeatedly declaring the field.

巧合的是,当按照我的问题( inspectdb -> makemigrations -> migration )为现有数据库创建初始迁移时,Django遍历模型以字母顺序按相同顺序创建表,并忽略其中的外键.它按字母顺序创建表,然后在以后对其进行修改以包括外键,从而破坏了现有数据库中可能存在的任何数据.似乎必须首先将外键定义为整数字段,然后再将其更改为让Django管理表的方式.另一种方法是,可以注释掉所有模型,并以解决外键的方式取消注释,从而生成迁移.然后,Django将相应地链接它们.然后可以将迁移压缩为单个迁移,并将其设置为初始迁移.

Coincidentally when one creates the initial migration for an existing database as described in my question (inspectdb -> makemigrations -> migrate), Django traverses the models alphabetically creating tables in the same order and ignoring ones foreign keys. It creates the tables alphabetically and then modifies them later to include foreign keys, clobbering any data that might be present in a existing database. It seems one must define the foreign keys as integer fields initially and change them back as one lets Django manage the tables. Alternatively one can comment out all of their models and generate migrations as one uncomments them in a fashion that resolves the foreign keys; Django will then link them accordingly. One may then squash the migrations into a single migration and set this as the initial migration.

这篇关于Django不断迁移相同的外键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆