如果 AddField 引用 "same" 列,则使用“--fake-initial”的 Django 迁移不起作用

Django migration with "--fake-initial" is not working if AddField referes to "same" column

我正在玩 django(我是一个相当新的初学者)并且在网上冲浪时我读到可以在 mySQL 数据库中保留我们内部的 camelCase 命名约定,并且对于models.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, "Table 'city' already exists")'

只有使用 --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

这里,据我了解,没有区分大小写的比较,因此在 "column_names":

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

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


所以首先让我们把事情弄清楚。您提到 --lower-case-table-names=0 已启用,但排序规则不区分大小写。 From the docs 我看到该选项强制 table 名称区分大小写。我可能只是读错了,但看起来你是在说一切都应该不区分大小写。此外,排序规则通常指的是数据本身,而不是列名,以防你不知道。

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

看起来你只是在玩,所以我认为你不是在寻找特定的解决方案。也许下一步是 file a bug ;)?据我所知,在那里添加不区分大小写的比较没有任何缺点,但从事 Django 24/7 工作的人可能有不同的意见。