Django创建了一个迁移,这个迁移似乎已经反映在原来的postgresql模式中



我已经修改了外键日历在我的Django模型CalendarAssign

# ---------------------------------------------------------------------------- #
class Calendars(models.Model):
id = models.CharField(primary_key=True, max_length=100)
cms_id = models.CharField(max_length=100)
default_program = models.ForeignKey(ControlPrograms, models.CASCADE, blank=True, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
managed = True
db_table = 'calendars'
# ---------------------------------------------------------------------------- #
class CalendarAssign(models.Model):
device_mac = models.ForeignKey(Device, models.CASCADE)
calendar = models.ForeignKey(Calendars, models.CASCADE, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
managed = True
db_table = 'calendar_assign'

当应用Django生成的迁移时,它给了我一个错误。

operations = [
migrations.AlterField(
model_name='calendarassign',
name='calendar',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='smartbridge.Calendars'),
)

生成的sql代码使用不支持的特性'WITH ORDINALITY'。这是因为Django不支持我们使用的postges版本。
WITH ORDINALITY出现在psql 9.4中,但我们使用9.1版本。
Postgres和Django现在都不能升级。所以我需要手动编写迁移(没有'WITH ORDINALITY'功能)。

migrations.RunSQL("DO $$DECLARE r record;
BEGIN
FOR r IN SELECT table_name,constraint_name 
FROM information_schema.constraint_table_usage 
WHERE table_name IN ('calendars') AND constraint_name like '%calendar_assign_calendar_id%'
LOOP
EXECUTE 'ALTER TABLE calendar_assign DROP CONSTRAINT '|| quote_ident(r.constraint_name) || ';';
END LOOP;
ALTER TABLE calendar_assign ALTER COLUMN calendar_id DROP NOT NULL; 
ALTER TABLE calendar_assign 
ADD CONSTRAINT calendar_assign_calendar_id_fk_calendars_id FOREIGN KEY (calendar_id) REFERENCES calendars(id);
END$$;")

迁移似乎可以正常工作。日历现在是可空的,但是Django仍然检测到一些差异。
如果我要求Django生成相应的迁移,它生成的差异与我手动迁移之前相同。

我希望Django在我迁移之后没有看到任何不同。

感谢

我认为您暂时必须设置managed = False,否则makemigrations命令每次都会认为它尚未设置为空。

迁移构造命令查看以前的迁移文件,从而构造一个概念性模型,如果发生了所有以前的迁移,那么数据库中的表将是什么样子。基于该模型,它将查找与你构建的Django模型的差异,并因此创建一个迁移文件。

只要你没有使用AlterField命令迁移,Django就会认为你没有将字段设置为空。它不能解析SQL,所以即使你在那里设置为空,它仍然会假设该字段是非空的。

设置为managed=False[Django-doc], Django将不再管理该文件的迁移。你可以创建一个空的迁移文件[Django-doc]:

python3 manage.py makemigrations--empty

,并使用它来定义要在表上执行的SQL查询。

最新更新