{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreiat2l2vi6hyuuhejp5r45f3yxnifq4obzludntcfmowq4qkf5zxfy",
    "uri": "at://did:plc:lckpdfkbaacxngbnob45e5vg/app.bsky.feed.post/3mltt3cyowf72"
  },
  "path": "/2026/05/14/disappearing-materialized-view",
  "publishedAt": "2026-05-14T18:45:00.000Z",
  "site": "https://craiga.id.au",
  "tags": [
    "materialized views",
    "Postgres’ documentation"
  ],
  "textContent": "A project I’ve been working on depends on a number of materialized views, a nifty feature of Postgres which is somewhere between a traditional view and a table.\n\nIf you’ve got some complex query that takes a long time to run, materialized views can be very useful. A materialized view will run that complex query, store the result, and then return that stored result to anyone who queries that view.\n\nHere’s an example materialized view, adapted from Postgres’ documentation to demonstrate how this might work when querying tables created by Django:\n\n\n    CREATE MATERIALIZED VIEW sales_summary AS SELECT seller_no, invoice_date, sum(invoice_amt)::numeric(13,2) as sales_amt FROM invoices_invoice WHERE invoice_date < CURRENT_DATE GROUP BY seller_no, invoice_date;\n\n…and here’s what that Django model might look like:\n\n\n    class Invoice(models.Model): seller_no = models.IntegerField() invoice_date = models.DateField() invoice_amt = models.DecimalField( max_digits=13, decimal_places=2 )\n\nIf you try to drop a column used by a materialized view in Postgres, you’ll get an error:\n\n\n    mydb=> ALTER TABLE invoices_invoice DROP COLUMN invoice_date; ERROR: cannot drop column invoice_date of table invoice because other objects depend on it DETAIL: materialized view sales_summary depends on column invoice_date of table invoices_invoice HINT: Use DROP ... CASCADE to drop the dependent objects too.\n\nHowever, if you drop that column via a Django migration, you get no such error. This is because Django will drop the column using that `CASCADE` keyword. That will cause the materialized view to be deleted silently.\n\n\n    ./manage.py sqlmigrate invoices 0002_remove_invoice_date BEGIN; -- -- Remove field invoice_date from invoice -- ALTER TABLE \"invoices_invoice\" DROP COLUMN \"invoice_date\" CASCADE; COMMIT;\n\nI haven’t been able to find a way to work around this. If you happen to know one, please reach out and I’ll update this post.",
  "title": "Django and the curious case of the disappearing materialized view",
  "updatedAt": "2026-05-14T18:45:00.000Z"
}