Django-taggit 迁移在 AlterUniqueTogether 失败
Django-taggit migration fails at AlterUniqueTogether
我正在尝试迁移使用 jazzband django-taggit 的 Django 应用程序
我得到的错误是:
django.db.utils.IntegrityError: could not create unique index "taggit_taggeditem_content_type_id_object_i_4bb97a8e_uniq"
DETAIL: Key (content_type_id, object_id, tag_id)=(41, 596, 242) is duplicated.
有问题的迁移如下:
migrations.AlterUniqueTogether(
name="taggeditem", unique_together={("content_type", "object_id", "tag")}
)
转换为以下 SQL:
ALTER TABLE "taggit_taggeditem" ADD CONSTRAINT "taggit_taggeditem_content_type_id_object_i_4bb97a8e_uniq" UNIQUE ("content_type_id", "object_id", "tag_id");
COMMIT;
检查有问题的 table 我得到:
# SELECT * FROM public.taggit_taggeditem WHERE tag_id=242 ORDER BY object_id;
id | tag_id | object_id | content_type_id
------+--------+-----------+-----------------
691 | 242 | 356 | 41
2904 | 242 | 356 | 41
680 | 242 | 486 | 41
2893 | 242 | 486 | 41
683 | 242 | 596 | 41
2896 | 242 | 596 | 41
解决 django.db.utils.IntegrityError
错误并成功完成迁移的建议方法是什么?我认为 object_id 486 和 356(+ 几个)也会发生同样的情况。
在迁移模型之前,你应该做一个data migration。因此,您最好先删除迁移文件,然后使用以下命令进行数据迁移:
python3 manage.py makemigrations <b>--empty</b> <i>app_name</i>
在此迁移中可能如下所示:
from django.db import migrations
from django.db.models import Exists, OuterRef
def remove_duplicates(apps, schema_editor):
Model = apps.get_model(<i>'app_name'</i>, <i>'ModelName'</i>)
Model.objects.annotate(
has_dup=Exists(
Model.objects.filter(
pk__lt=OuterRef('pk'),
<b>content_type_id=OuterRef('content_type_id')</b>,
<b>object_id=OuterRef('object_id')</b>,
<b>tag_id=OuterRef('tag_id')</b>,
)
)
).filter(has_dup=True).delete()
class Migration(migrations.Migration):
dependencies = [
('<i>app_name</i>', '<i>1234_some_migration</i>'),
]
operations = [
migrations.RunPython(remove_duplicates),
]
将 app_name
和 ModelName
分别替换为应用名称和型号(并检查它是否依赖于之前的迁移文件)。
因此,我们在这里寻找包含主键小于当前主键的重复数据的 Model
s。我们删除此类记录。
接下来您再次为应用程序进行迁移:
python3 manage.py makemigrations <i>app_name</i>
我会(强烈)建议在 运行 之前先备份数据库,因为数据迁移总是有可能出现复杂的问题。
我正在尝试迁移使用 jazzband django-taggit 的 Django 应用程序 我得到的错误是:
django.db.utils.IntegrityError: could not create unique index "taggit_taggeditem_content_type_id_object_i_4bb97a8e_uniq"
DETAIL: Key (content_type_id, object_id, tag_id)=(41, 596, 242) is duplicated.
有问题的迁移如下:
migrations.AlterUniqueTogether(
name="taggeditem", unique_together={("content_type", "object_id", "tag")}
)
转换为以下 SQL:
ALTER TABLE "taggit_taggeditem" ADD CONSTRAINT "taggit_taggeditem_content_type_id_object_i_4bb97a8e_uniq" UNIQUE ("content_type_id", "object_id", "tag_id");
COMMIT;
检查有问题的 table 我得到:
# SELECT * FROM public.taggit_taggeditem WHERE tag_id=242 ORDER BY object_id;
id | tag_id | object_id | content_type_id
------+--------+-----------+-----------------
691 | 242 | 356 | 41
2904 | 242 | 356 | 41
680 | 242 | 486 | 41
2893 | 242 | 486 | 41
683 | 242 | 596 | 41
2896 | 242 | 596 | 41
解决 django.db.utils.IntegrityError
错误并成功完成迁移的建议方法是什么?我认为 object_id 486 和 356(+ 几个)也会发生同样的情况。
在迁移模型之前,你应该做一个data migration。因此,您最好先删除迁移文件,然后使用以下命令进行数据迁移:
python3 manage.py makemigrations <b>--empty</b> <i>app_name</i>
在此迁移中可能如下所示:
from django.db import migrations
from django.db.models import Exists, OuterRef
def remove_duplicates(apps, schema_editor):
Model = apps.get_model(<i>'app_name'</i>, <i>'ModelName'</i>)
Model.objects.annotate(
has_dup=Exists(
Model.objects.filter(
pk__lt=OuterRef('pk'),
<b>content_type_id=OuterRef('content_type_id')</b>,
<b>object_id=OuterRef('object_id')</b>,
<b>tag_id=OuterRef('tag_id')</b>,
)
)
).filter(has_dup=True).delete()
class Migration(migrations.Migration):
dependencies = [
('<i>app_name</i>', '<i>1234_some_migration</i>'),
]
operations = [
migrations.RunPython(remove_duplicates),
]
将 app_name
和 ModelName
分别替换为应用名称和型号(并检查它是否依赖于之前的迁移文件)。
因此,我们在这里寻找包含主键小于当前主键的重复数据的 Model
s。我们删除此类记录。
接下来您再次为应用程序进行迁移:
python3 manage.py makemigrations <i>app_name</i>
我会(强烈)建议在 运行 之前先备份数据库,因为数据迁移总是有可能出现复杂的问题。