更新时Django物化视图迁移问题

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

我们正在使用 Postgres (v13) 在 Django (v4.0) 中构建一个库。这个库将成为我们公司的核心,所以我们必须小心迁移。当我们为任何物化视图更新基表时,问题出在 Django 迁移上。

  1. 型号:
  • 底座
class Customer(models.Model):
    external_id = models.CharField(max_length=50, unique=True)

    class Meta:
        db_table = "customer"
  • 物化视图
class CustomerDetailView(models.Model):
    id = models.CharField(max_length=50, primary_key=True)
    external_id = models.CharField(max_length=50, unique=True)
    
    class Meta:
        managed = False
        db_table = "customer_detail_view"
  1. 迁移:
  • “0001_initial.py”由 Django 创建
class Migration(migrations.Migration):
    ...

    operations = [
        migrations.CreateModel(
            name='CustomerDetailView',
            fields=[
                ('id', models.CharField(max_length=50, primary_key=True, serialize=False)),
                ('external_id', models.CharField(blank=True, max_length=50)),
            ],
            options={
                'db_table': 'customer_detail_view',
                'managed': False,
            },
        ),
        migrations.CreateModel(
            name='Customer',
            fields=[
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ('external_id', models.CharField(blank=True, max_length=50, null=True, unique=True))
            ],
            options={
                'db_table': 'customer',
            },
        ),
  • “0002_customer_detail_view.py”手动创建
class Migration(migrations.Migration):

    dependencies = [
        ("customers", "0001_initial"),
    ]

    operations = [
        migrations.RunSQL(
            """
            DROP MATERIALIZED VIEW IF EXISTS customer_detail_view;
            CREATE MATERIALIZED VIEW customer_detail_view AS
            SELECT
                cus.id,
                cus.external_id,
            FROM
                customer cus;
            CREATE UNIQUE INDEX customer_detail_view_pk ON customer_detail_view(external_id);
            """,
            "DROP MATERIALIZED VIEW customer_detail_view"
        )
    ]
  • “0003_alter_customer_external_id.py”由 Django 在对基表进行虚拟修改后创建
class Migration(migrations.Migration):

    dependencies = [
        ('customers', '0002_customer_detail_view'),
    ]

    operations = [
        migrations.AlterField(
            model_name='customer',
            name='external_id',
            field=models.CharField(blank=True, max_length=60, null=True, unique=True),
        ),
    ]
  1. 错误
  • 发生在我们做
    python manage.py migrate
Running migrations:
  Applying customers.0003_alter_customer_external_id...Traceback (most recent call last):
  File "/usr/app/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.FeatureNotSupported: cannot alter type of a column used by a view or rule
DETAIL:  rule _RETURN on materialized view customer_detail_view depends on column "external_id"

我们认为问题与“0001_initial.py”迁移有关,其中 Django(即使物化视图是带有

managed=False
的表)创建迁移,然后在更新基础时无法为创建迁移物化视图。

python django materialized-views
1个回答
0
投票

Django 默认不支持物化视图迁移。这就是为什么你应该手动编写迁移。在删除实体化视图之前,您无法使用字段

Customer
更改模型
external_id
(如果实体化视图是从
Customer
模型和字段
external_id
创建的)。您可以创建自定义迁移以删除物化视图并应用模型更改,然后再次创建您的物化视图。但是有一个简单的解决方案来管理它:

您可以使用此库将物化视图集成到 Django django-materialized-view

你需要的一切:

  1. 获取view_definitions(如果你现在不查询物化视图):
SELECT *
FROM information_schema.views
WHERE table_schema = 'information_schema'
AND table_name = 'views';
  1. 根据描述使用django-materialized-view
  2. 享受项目中的物化视图。
© www.soinside.com 2019 - 2024. All rights reserved.