Django 4:如何将 MultiPolygonField 从可空修改为非空

问题描述 投票:0回答:2

我正在尝试从中转换我的 MultiPolygonField 字段:

multipolygon = MultiPolygonField(null=True)

对此:

multipolygon = MultiPolygonField(null=False)

它看起来很简单,所以我执行“makemigrations”,我得到了通常的消息警告,即数据库需要一些东西来填充现有的行(我确认我的数据库中没有该字段为空的行):

我是否选择选项1:

  1. 现在提供一次性默认值(将在所有现有行上设置 此列为空值)

并将以下设置为默认值:

'SRID=3857;POINT(0.0 0.0)'

或选项2:

  1. 暂时忽略。包含 NULL 值的现有行将必须 手动处理,例如使用 RunPython 或 RunSQL 操作

执行“迁移”时出现以下错误:

ValueError: Cannot alter field borders.Border.multipolygon into borders.Border.multipolygon - 它们没有正确定义 db_type(是 你使用了一个写得不好的自定义字段?)

我已经能够毫无问题地对其他更简单的字段类型进行相同的更改。如何使用 MultiPolygonFields 做到这一点? 我正在使用 Django 4 和 sqlite 3.31,以防万一。

django sqlite django-models geodjango django-4.0
2个回答
1
投票

您遇到的问题与 MultiPolygonField 没有正确的数据库类型定义有关。自定义字段或未正确定义其数据库类型的第三方字段可能会发生这种情况。

要解决此问题,您可以尝试以下步骤:

从您的字段定义中删除 null=True:

multipolygon = MultiPolygonField()

运行 makemigrations 为这个变化创建一个新的迁移。

在迁移文件中,手动编辑 AlterField 操作以包含现有行的默认值:

from django.contrib.gis.geos import GEOSGeometry

类迁移(迁移。迁移):

dependencies = [
    ('yourapp', '000x_previous_migration'),
]

operations = [
    migrations.AlterField(
        model_name='yourmodel',
        name='multipolygon',
        field=models.MultiPolygonField(default=GEOSGeometry('SRID=3857;POINT(0.0 0.0)')),
    ),
]

我们将默认值设置为 GEOSGeometry('SRID=3857;POINT(0.0 0.0)'),这是一个在 (0, 0) 处具有 SRID 3857 的点。

运行迁移以应用迁移。

如果您的现有行的多面体字段具有空值,您可以手动更新它们或使用 RunPython 或 RunSQL 操作来设置它们的值。例如,您可以使用以下 RunPython 操作为所有空行设置默认值:

    from django.contrib.gis.geos import GEOSGeometry

def set_multipolygon_default(apps, schema_editor):
    YourModel = apps.get_model('yourapp', 'YourModel')
    YourModel.objects.filter(multipolygon__isnull=True).update(multipolygon=GEOSGeometry('SRID=3857;POINT(0.0 0.0)'))

class Migration(migrations.Migration):

    dependencies = [
        ('yourapp', '000x_previous_migration'),
    ]

    operations = [
        migrations.RunPython(set_multipolygon_default),
    ]

此操作将使用我们在上一步中设置的默认值更新所有 multipolygon 为空的行。

希望对您有所帮助!


0
投票

这就是我最终“解决”问题的方式(没有完全解决,但我找到了更长的方法来获得相同的结果):

我把迁移分为6个步骤:

  1. 我创建了一个新字段“multipolygon_new”
  2. 我将数据从我的初始字段“multipolygon”复制到我刚刚创建的新字段“multipolygon_new”
  3. 我删除了我的初始字段“multipolygon”
  4. 我再次创建了“多边形”,但不是空的
  5. 我将数据从“multipolygon_new”复制到“”multipolygon”
  6. 我删除了“multipolygon_new”

对于第 2 步和第 5 步,使用以下命令创建自定义迁移:

python manage.py makemigrations --empty yourappname

然后我修改了迁移文件以执行我的自定义复制查询:

migrations.RunSQL(
    sql=[("UPDATE mytable ......", ],
)

对于其他步骤,我使用了常用的 makemigrations 命令。

© www.soinside.com 2019 - 2024. All rights reserved.