我正在尝试将 SERIAL 非主列添加到现有表中。 Django 似乎不支持这一点(AutoField 必须是主要的,我无法将此字段设为主要)。
但是postgres确实支持SERIAL列,所以在生成的迁移文件中我可以添加以下操作:
class Migration(migrations.Migration):
dependencies = [
...
]
operations = [
migrations.RunSQL(
sql="ALTER TABLE portal_referral ADD referral_id SERIAL;",
reverse_sql="ALTER TABLE portal_referral DROP referral_id;"
)
]
但是,Django 似乎并未“注册”此迁移的影响。也就是说,当再次运行
manage.py makemigrations
时,该工具将尝试在新的迁移中再次添加 referral_id
。
模型定义为
class Referral(utils.UUIDPrimaryKeyBase, utils.TimeStampedModel):
data = models.JSONField(encoder=DjangoJSONEncoder)
supplier = models.ForeignKey(Supplier, blank=True, null=True, on_delete=models.PROTECT, related_name="referrals")
session_id = models.UUIDField(editable=False, blank=True, null=True, unique=True)
referral_id = models.IntegerField()
def __str__(self):
return f"<referral id={self.id} supplier={self.supplier}>"
我确实找到了一种方法来解决这个问题,在让迁移生成其代码之后,我可以随后插入一些覆盖的 SQL 语句。
class Migration(migrations.Migration):
dependencies = [
...
]
operations = [
migrations.AddField(
model_name='referral',
name='referral_id',
field=models.IntegerField(default=0),
preserve_default=False,
),
migrations.RunSQL(
sql="ALTER TABLE portal_referral DROP referral_id;",
reverse_sql="ALTER TABLE portal_referral ADD referral_id INT DEFAULT 0;"
),
migrations.RunSQL(
sql="ALTER TABLE portal_referral ADD referral_id SERIAL;",
reverse_sql="ALTER TABLE portal_referral DROP referral_id;"
)
]
这确实有效,但似乎不是特别有效。有没有办法向 Django 标记我自己添加了此字段并且不需要添加列本身?
您可以利用 RunSQL state_operations
migrations.RunSQL(
sql="ALTER TABLE portal_referral ADD referral_id SERIAL;",
reverse_sql="ALTER TABLE portal_referral DROP referral_id;",
state_operations=[
migrations.AddField(
"referral",
"referral_id",
field=models.IntegerField(default=0),
preserve_default=False,
),
],
)