如果 AddField 引用“相同”列,则带有“--fake-initial”的 Django 迁移不起作用
Posted
技术标签:
【中文标题】如果 AddField 引用“相同”列,则带有“--fake-initial”的 Django 迁移不起作用【英文标题】:Django migration with "--fake-initial" is not working if AddField referes to "same" column 【发布时间】:2019-03-05 22:50:38 【问题描述】:我正在玩 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, "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']
【问题讨论】:
【参考方案1】:首先,我要祝贺您完成第一个问题!许多年长的贡献者没有你那么深入。
所以首先让我们把事情弄清楚。您提到 --lower-case-table-names=0
已启用,但排序规则不区分大小写。 From the docs 我看到该选项强制表名区分大小写。我可能只是读错了,但看起来你说一切都应该不区分大小写。此外,排序规则通常指的是数据本身,而不是列名,以防您不知道。
据我所知,所有数据库都以不区分大小写的方式处理列名(我刚刚在 SQLite 中进行了测试),因此您可能刚刚发现了 Django 中的一个错误!我查看了该文件的历史,在该代码存在的 5 多年中,我想没有人遇到过这个问题。这是可以理解的,因为通常人们要么 a) 让 django 从头开始创建数据库,因此一切都是同步的,或者 b) 他们使用 inspectdb
为列生成具有正确大小写的代码。
看起来你只是在玩,所以我认为你不是在寻找特定的解决方案。也许下一步是file a bug ;)?据我所知,在那里添加不区分大小写的比较不会有任何不利之处,但是从事 Django 24/7 工作的人可能会有不同的意见。
【讨论】:
年长的贡献者我猜他们知道他们做什么并且不会像我一样受到impostor syndrome 的影响,所以在询问/发布之前,我会仔细检查并调试所有内容 :-) 我注册了一个帐户并提交了一个ticket@django,让我们看看他们是怎么想的,同时我使用 django 的套管样式作为列和模型。感谢您的回答! 对新用户的另一个提示 - 如果您对答案感到满意,请单击左侧的复选标记。它有助于改善已解决问题与未解决问题的统计数据。以上是关于如果 AddField 引用“相同”列,则带有“--fake-initial”的 Django 迁移不起作用的主要内容,如果未能解决你的问题,请参考以下文章
如果 char(2) 的列具有两个空格的默认值,则 Linq 引用不返回任何项目