Package: django-materialized-view
Materialized View support for the Django framework. Django (in general) does not support materialized views by the default
therefor migrations are not created automatically with./manage.py makemigrations.
This library provides newmanage.pycommand:./manage.py migrate_with_views.
This command is to be used instead of the default onemigrate.This command automatically finds your materialized view models and keeps them up to date.
In case when materialized view is a parent view for another materialized view, usemigrate_with_viewscommand
in order to change query of parent materialized view.migrate_with_viewscommand finds all related materialized views and recreates them sequentially.ContentsRequirementsInstallationUsageCreate class and inherit from MaterializedViewModelAdd materialized view query (You can create a materialized view either from Raw SQL or from a queryset)Create materialized view from Raw SQLCreate materialized view query from QuerysetUse refresh method to update materialized view dataRequirementsdjango-materialized-view has been tested with:Django: 4.0, 4.1Python: 3.9, 3.10, 3.11Postgres >= 13InstallationVia pip into avirtualenv:pipinstalldjango-materialized-viewInsettings.pyadd the following:INSTALLED_APPS=(...'django_materialized_view')Before running migrate:pythonmanage.pymigrateThen you can use new migrate command instead of the default one:pythonmanage.pymigrate_with_viewsThis command will automatically begin interception of materialized view models,
and proceed to create/delete/update your view on your DB if required.UsageCreate class and inherit fromMaterializedViewModelEXAMPLE:fromdjango.dbimportmodelsfromdjango_materialized_view.base_modelimportMaterializedViewModelclassMyViewModel(MaterializedViewModel):create_pkey_index=True# if you need add unique field as a primary key and create indexesclassMeta:managed=False# if create_pkey_index=True you must add argument primary_key=Trueitem=models.OneToOneField("app.ItemModel",on_delete=models.DO_NOTHING,primary_key=True,db_column="id")from_seconds=models.IntegerField()to_seconds=models.IntegerField()type=models.CharField(max_length=255)# ATTENTION: this method must be a staticmethod or classmethod@staticmethoddefget_query_from_queryset():# define this method only in case use queryset as a query for materialized view.# Method must return QuerysetpassAdd materialized view query (You can create a materialized view either from Raw SQL or from a queryset)Create materialized view from Raw SQLrun django defaultmakemigrationscommand for creating model migrations if necessary:./manage.py makemigrationsrunmigrate_with_viewscommand for getting your new sql file name and path:./manage.py migrate_with_viewsyou will get file path in your console[Errno 2] No such file or directory: '.../app/models/materialized_views/sql_files/myviewmodel.sql' - please create SQL file and put it to this directorycreate file on suggested path with suggested namerun again django commandmigrate_with_views:./manage.py migrate_with_viewsthis command will run the defaultmigratecommand and apply materialized viewsCreate materialized view query from Querysetrun django defaultmakemigrationscommand for creating model migrations if necessary:./manage.py makemigrationsadd to your materialized view model the methodget_query_from_queryset:# ATTENTION: this method must be a staticmethod or classmethod@staticmethoddefget_query_from_queryset():returnSomeModel.objects.all()run django commandmigrate_with_views:./manage.py migrate_with_viewsThis command will run defaultmigratecommand and apply materialized viewsUserefreshmethod to update materialized view data.For updating concurrently:MyViewModel.refresh()For updating non-concurrently:MyViewModel.refresh(concurrently=Fasle)Note: All refreshes will be logged in to the model MaterializedViewRefreshLog:classMaterializedViewRefreshLog(models.Model):updated_at=models.DateTimeField(auto_now_add=True,db_index=True)duration=models.DurationField(null=True)failed=models.BooleanField(default=False)view_name=models.CharField(max_length=255)DevelopmentRelease CI triggered on tags. To release new version, create the release with new tag on GitHubFor integration with pytest add following fixture:@pytest.fixture(scope="session")defdjango_db_setup(django_db_setup,django_db_blocker):withdjango_db_blocker.unblock():view_processor=MaterializedViewsProcessor()view_processor.process_materialized_views()