Geodjango:使用迁移将现有数据的 PolygonField 更改为 MultiPolygon Field

Geodjango: Change PolygonField to MultiPolygonField with exisiting data using a migration

我有一个 PolygonField 的模型,它有几十行。我正在尝试将字段更改为 MultiPolygonField,但数据仍处于 polygon 模式。如何将所有现有数据转换为新类型?

models.py:

class Region(models.Model):
    class Meta:
        verbose_name = _("region")
        verbose_name_plural = _("regions")

    polygon = models.PolygonField(_("polygon"))  # <== this is going to be MultiPolygon
    name = models.CharField(_("name"), max_length=100)

选项 1:使用 SQL

假设你使用的是postgis,下面SQL可以使用ST_Multi转换你的数据:

ALTER TABLE myapp_region
    ALTER COLUMN polygon TYPE geometry(MultiPolygon, 4326)
    USING ST_Multi(polygon);

不要直接执行这个,而是 运行 makemigrations 这将创建一个新的迁移(例如:myapp/migrations/0006_yyyyyyyy.py)类似于:

import django.contrib.gis.db.models.fields
from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0005_zzzzzzzzzzzzz'),
    ]

    operations = [
        migrations.AlterField(
            model_name='region',
            name='polygon',
            field=django.contrib.gis.db.models.fields.MultiPolygonField(srid=4326),
        ),
    ]

用这样的 RunSQL 操作封装您的 AlterField 操作:

operations = [
    migrations.RunSQL(
        "ALTER TABLE myapp_region ALTER COLUMN polygon type geometry(MultiPolygon, 4326) using ST_Multi(polygon);",
        state_operations=[
            migrations.AlterField(
                model_name='region',
                name='polygon',
                field=django.contrib.gis.db.models.fields.MultiPolygonField(
                    srid=4326),
            ),
        ],
    )
]

现在 运行 您的迁移。

选项 2:数据迁移

  • 在当前字段旁边创建一个新的 geom = models.MultiPolygonField(null=True) 字段。
  • 创建并运行 迁移以添加新的多面字段。
  • 创建一个data migration and use RunPython来复制你的数据:

    for o in Region.objects.all():
        o.geom = MultiPolygon([o.polygon])
        o.save()
    

    (未经测试:您也许可以使用 Region.objects.update()

  • models.py中,删除原来的字段,去掉null=True;创建迁移。
  • 可选:使用另一个迁移将 geom 重命名为 polygon