如果AddField引用“相同”列,则无法使用“ --fake-initial”进行Django迁移

时间:2018-09-30 18:13:43

标签: python django python-3.x django-migrations

我正在玩django(我是一个相当新的初学者),在浏览网络时,我读到了可以将我们的内部camelCase命名约定保留在mySQL数据库中以及在模型内部保留模型名称的可能。 py

好吧,几天后,我可以得出结论,最好将它们保留为设计状态,并使用inspectdb生成的标准输出,而无需对其代码进行任何更改(我删除了.lower()函数:- )

无论如何,出于好奇,如果有人可以向我解释为什么以下内容不起作用,我将不胜感激。简而言之,在我看来,负责迁移的代码没有正确检查(?)数据库中是否已存在列名,或者至少它以区分大小写的方式进行了比较。是设计使然吗?

我正在通过互联网https://datascience.blog.wzb.eu/2017/03/21/using-django-with-an-existinglegacy-database/

使用本指南

mysql正在使用选项" --lower-case-table-names=0"运行,并且排序规则不区分大小写。

models.py里面我有这个

class City(models.Model):
    id = models.AutoField(db_column='ID', primary_key=True)
    name = models.CharField(db_column='Name', max_length=35)
    countrycode = models.ForeignKey(Country, db_column='CountryCode')
    district = models.CharField(db_column='District', max_length=20)
    population = models.IntegerField(db_column='Population', default=0)

    def __str__(self):
        return self.name

    class Meta:
        managed = True
        db_table = 'city'
        verbose_name_plural = 'Cities'
        ordering = ('name', )

如果我将引用'db_column'更改为db_column='countryCode'(请注意下面的“ c”),然后我运行

./manage.py migrate --database world_data --fake-initial worlddata

我收到说'django.db.utils.OperationalError:(1050,“表'city'已经存在”))的错误消息

仅使用--fake-initial选项会出现问题

分析“ ... django / db / migrations / executor.py”后,我发现了这些行,用于检查现有列中是否已存在列

column_names = [
    column.name for column in
    self.connection.introspection.get_table_description(self.co$
]
if field.column not in column_names:
    return False, project_state

据我所知,这里没有区分大小写的比较,因此在"countryCode"内找不到"column_names"列:

-> if field.column not in column_names:
(Pdb) field.column
'countryCode'
(Pdb) column_names
['ID', 'Name', 'CountryCode', 'District', 'Population']

1 个答案:

答案 0 :(得分:2)

首先,我要祝贺您完成第一个问题!许多年长的贡献者没有您那么深入。


所以首先让我们弄清楚。您提到--lower-case-table-names=0已启用,但排序规则不区分大小写。 From the docs我看到该选项强制对表名区分大小写。我可能只是看错了,但似乎您是在说所有内容都不区分大小写。此外,排序规则通常是指数据本身,而不是您不知道的列名。

据我所知,所有数据库都不区分列名区分大小写(我刚刚在SQLite中进行了测试),因此您可能刚刚发现Django中的一个错误!我查看了文件的历史记录,发现代码已经存在了5多年了,我猜没有人遇到这个问题。这是可以理解的,因为通常人们要么a)只是让django从头开始创建数据库,从而一切都同步,要么b)他们使用inspectdb生成具有正确列大小写的代码。

似乎您只是在玩耍,所以我不认为您正在寻找特定的解决方案。也许下一步是file a bug;)?从我看来,在那里添加不区分大小写的比较没有任何弊端,但是从事Django 24/7的人们可能会有不同的看法。