Django PGViews Redux

1.2.0 · active · verified Fri Apr 17

django-pgviews-redux is a Django library designed to manage PostgreSQL views, including materialized views, as part of your Django models and migrations. It provides tools to define SQL views in your Django applications, track their schema changes, and integrate them seamlessly into your database lifecycle. The current version is 1.2.0, with an active but irregular release cadence.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to define both a regular and a materialized PostgreSQL view in a Django application. Views are defined as Django models that inherit from `PostgresView` or `MaterializedView` mixins. Remember to set `managed = False` in the `Meta` class and include an `id` field as a primary key. Materialized views require explicit refreshing to update their data.

import os
from django.db import models
from pgviews.view import PostgresView
from pgviews.materialized_view import MaterializedView

# Assuming 'myapp' is an installed Django app
# Add 'pgviews' to INSTALLED_APPS in settings.py:
# INSTALLED_APPS = [
#    ...,
#    'myapp',
#    'pgviews',
# ]

# Define a base model for demonstration
class Author(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

    def __str__(self):
        return self.title

# Define a regular PostgreSQL View
class AuthorBookCountView(PostgresView, models.Model):
    # The SQL query must define an 'id' field, as Django models require a primary key.
    view_definition = """
        SELECT
            a.id AS id,
            a.name AS author_name,
            COUNT(b.id) AS book_count
        FROM myapp_author a
        LEFT JOIN myapp_book b ON a.id = b.author_id
        GROUP BY a.id, a.name
    """

    id = models.IntegerField(primary_key=True)
    author_name = models.CharField(max_length=100)
    book_count = models.IntegerField()

    class Meta:
        # Important: Django should not manage the creation/deletion of the view itself.
        managed = False
        db_table = 'author_book_count_view' # Explicitly set db_table for clarity

# Define a Materialized PostgreSQL View
class MaterializedAuthorBookCountView(MaterializedView, models.Model):
    view_definition = """
        SELECT
            a.id AS id,
            a.name AS author_name,
            COUNT(b.id) AS book_count
        FROM myapp_author a
        LEFT JOIN myapp_book b ON a.id = b.author_id
        GROUP BY a.id, a.name
    """

    id = models.IntegerField(primary_key=True)
    author_name = models.CharField(max_length=100)
    book_count = models.IntegerField()

    class Meta:
        managed = False
        db_table = 'materialized_author_book_count_view'

    def refresh_data(self):
        self.refresh() # Method provided by MaterializedView mixin

# To use:
# 1. Add 'pgviews' and 'myapp' to INSTALLED_APPS in settings.py.
# 2. python manage.py makemigrations myapp
# 3. python manage.py migrate
# 4. To query: AuthorBookCountView.objects.all()
# 5. To refresh materialized view: MaterializedAuthorBookCountView.objects.first().refresh_data() or MaterializedAuthorBookCountView.objects.refresh()

view raw JSON →