我已经修改了外键日历在我的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查询。