Django+SpatiaLite含PolygonField模型迁移IntegrityError问题求解
解决Django含PolygonField模型迁移的IntegrityError错误
修改包含PolygonField的Django模型(对应数据库表)时,迁移操作终止并抛出以下错误:
django.db.utils.IntegrityError: The row in table 'geometry_columns_statistics' with primary key 'new__mc_sitio_benfeitoria' has an invalid foreign key: geometry_columns_statistics.f_table_name contains a value 'new__mc_sitio_benfeitoria' that does not have a corresponding value in geometry_columns.f_table_name.
我的应用名为MC_SITIO,相关模型代码如下:
class ImovelBase(ModelGis): """Base para Imóveis""" descricao = CharField(max_length=255, blank=False, null=True, verbose_name='descrição') administrador = ForeignKey(Pessoa, on_delete=SET_NULL, blank=True, null=True) RIP = CharField(max_length=255, blank=True, null=True, help_text='se for imóvel da União') codigo = CharField(max_length=255, blank=True, null=True, verbose_name='código, matricula, anúncio, ou outro documento') endereco = ForeignKey(Endereco, on_delete=SET_NULL, blank=True, null=True, verbose_name = 'endereço') poligono = PolygonField(srid=EPSG_SRID_PADRAO, blank=True, null=True, verbose_name='polígono') # area_total = UnumCharField(valid_unit=m**2, max_length=255, null=True, blank=True, verbose_name='área total', validators = [MinValueValidator(0.0)]) area_total = SympyCharField(max_length=255, null=True, blank=True, verbose_name='área total') VUP = DecimalField(null=True, blank=True, verbose_name='valor unitário padrão (VUP)', max_digits=11, decimal_places=2, validators = [MinValueValidator(0.0)]) indice_fiscal = DecimalField(null=True, blank=True, verbose_name='índice fiscal', max_digits=11, decimal_places=2, validators = [MinValueValidator(0.0)]) em_condominio = BooleanField(default=False, blank=True, verbose_name='em condomínio') observacoes = TextField(null=True, blank=True, verbose_name='observações') class Meta: abstract = True def __str__(self): return "{0}".format(self.descricao) def area(self): if self.poligono: return self.poligono.transform(get_SRID_UTM_WGS84(self.poligono.centroid), clone=True).area*m**2 return "S/N" @property def popupConteudo(self): return '<a href="/terreno-{}.html" target="_blank">{}</a>'.format(self.id, self.descricao) class TerrenoBase(ImovelBase): """Base para Terreno, tombo""" relevo = CharField(choices=RelevoClasse.choices, max_length=255, blank=True, null=True, verbose_name='classe do relevo') forma_regular = BooleanField(default=False, blank=True, verbose_name='forma regular?') esquinas_qtd = PositiveSmallIntegerField(blank=True, null=True, verbose_name="quantidade de esquinas") # testada = UnumCharField(valid_unit=m, max_length=255, null=True, blank=True) testada = SympyCharField(max_length=255, null=True, blank=True) testadas_qtd = PositiveSmallIntegerField(blank=True, null=True, verbose_name="quantidade de testadas") # gabarito = UnumCharField(valid_unit=m, max_length=255, null=True, blank=True) gabarito = SympyCharField(max_length=255, null=True, blank=True) macrozoneamento = CharField(max_length=255, null=True, blank=True) zoneamento = CharField(max_length=255, null=True, blank=True) tombamentos = ManyToManyField(Referencia, blank=True, verbose_name='tombamento(s)') class Meta: abstract = True class Terreno(TerrenoBase): """Terreno, tombo""" pass class Benfeitoria(ImovelBase): """Benfeitoria, casa, prédio, galpão, ponte, edificação, ou qualquer outra construção permanente sobre um terreno""" terreno = ForeignKey(Terreno, on_delete=SET_NULL, blank=False, null=True) tipob = PositiveSmallIntegerField(choices=BenfeitoriaTipo.choices, blank=False, null=True, verbose_name='tipo da benfeitoria') pav_desc = CharField(max_length=255, null=True, blank=True, verbose_name='descrição dos pavimentos', help_text='T: térreo, PT: pav. tipo, LJ: loja, C: cobertura, etc') rr_desc = CharField(choices=RossHeidecke.choices, max_length=255, null=True, blank=True, verbose_name='Critério de Ross-Heidecke') vida_util = CharField(choices=BenfeitoriaVidaUtilPadrao.choices, max_length=255, blank=True, null=True, verbose_name='vida útil padrão')
解决步骤
这个错误源于PostGIS的geometry_columns_statistics表残留了迁移临时表(带new__前缀)的记录,临时表已被迁移操作删除,导致外键约束失效。按以下步骤修复:
- 连接目标数据库:用psql、pgAdmin等工具连接到Django项目对应的PostgreSQL数据库。
- 清理无效统计记录:执行SQL删除无效条目:
DELETE FROM geometry_columns_statistics WHERE f_table_name = 'new__mc_sitio_benfeitoria'; - 重新执行迁移:回到项目目录,运行迁移命令:
python manage.py migrate - 预防后续问题(可选):若频繁出现此类问题,可在迁移前手动清理临时表相关统计记录,或检查Django与PostGIS版本兼容性,避免已知迁移bug。
内容的提问来源于stack exchange,提问作者Memória de Cálculo
相关产品推荐
相关产品推荐

