From b78546931b07ca649ee5c90b51c3552d26f81f77 Mon Sep 17 00:00:00 2001 From: Dmitry Groshev Date: Tue, 2 Jun 2020 23:20:44 +0100 Subject: [PATCH 1/2] use deepcopy during realize_deferred_projections, .copy() breaks ForeignKeys --- django_pgviews/view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django_pgviews/view.py b/django_pgviews/view.py index 9d67852..ec4ecb7 100644 --- a/django_pgviews/view.py +++ b/django_pgviews/view.py @@ -56,7 +56,7 @@ def realize_deferred_projections(sender, *args, **kwargs): # attribute or explicitly-defined field with that name. if hasattr(view_cls, name) or hasfield(view_cls, name): continue - copy.copy(field).contribute_to_class(view_cls, name) + copy.deepcopy(field).contribute_to_class(view_cls, name) models.signals.class_prepared.connect(realize_deferred_projections) From 6a9a4996df3f1935369dedd1a7f626cc98c7fe65 Mon Sep 17 00:00:00 2001 From: seroy Date: Thu, 6 Jun 2019 16:55:04 +0300 Subject: [PATCH 2/2] add support the database alias used for synchronization --- django_pgviews/apps.py | 4 ++-- django_pgviews/management/commands/clear_pgviews.py | 12 +++++++++++- django_pgviews/management/commands/sync_pgviews.py | 12 ++++++++---- django_pgviews/models.py | 12 +++++++----- django_pgviews/signals.py | 2 +- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/django_pgviews/apps.py b/django_pgviews/apps.py index 65aa994..7f40901 100644 --- a/django_pgviews/apps.py +++ b/django_pgviews/apps.py @@ -15,7 +15,7 @@ class ViewConfig(apps.AppConfig): name = "django_pgviews" verbose_name = "Django Postgres Views" - def sync_pgviews(self, sender, app_config, **kwargs): + def sync_pgviews(self, sender, app_config, using, **kwargs): """Forcibly sync the views. """ self.counter = self.counter + 1 @@ -28,7 +28,7 @@ def sync_pgviews(self, sender, app_config, **kwargs): from .models import ViewSyncer vs = ViewSyncer() - vs.run(force=True, update=True) + vs.run(force=True, update=True, using=using) def ready(self): """Find and setup the apps to set the post_migrate hooks for. diff --git a/django_pgviews/management/commands/clear_pgviews.py b/django_pgviews/management/commands/clear_pgviews.py index e11b0ca..a86ed4d 100644 --- a/django_pgviews/management/commands/clear_pgviews.py +++ b/django_pgviews/management/commands/clear_pgviews.py @@ -2,7 +2,7 @@ from django.core.management.base import BaseCommand from django.apps import apps -from django.db import connection +from django.db import DEFAULT_DB_ALIAS, connections from django_pgviews.view import clear_view, View, MaterializedView @@ -13,9 +13,19 @@ class Command(BaseCommand): help = """Clear Postgres views. Use this before running a migration""" + def add_arguments(self, parser): + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help='Nominates a database to synchronize. Defaults to the "default" database.', + ) + def handle(self, **options): """ """ + # Get the database we're operating from + db = options["database"] + connection = connections[db] for view_cls in apps.get_models(): if not (isinstance(view_cls, type) and issubclass(view_cls, View) and hasattr(view_cls, "sql")): continue diff --git a/django_pgviews/management/commands/sync_pgviews.py b/django_pgviews/management/commands/sync_pgviews.py index fbd361a..ede276f 100644 --- a/django_pgviews/management/commands/sync_pgviews.py +++ b/django_pgviews/management/commands/sync_pgviews.py @@ -2,8 +2,7 @@ import logging from django.core.management.base import BaseCommand -from django.db import connection -from django.apps import apps +from django.db import DEFAULT_DB_ALIAS from django_pgviews.models import ViewSyncer @@ -30,7 +29,12 @@ def add_arguments(self, parser): help="""Force replacement of pre-existing views where breaking changes have been made to the schema.""", ) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help='Nominates a database to synchronize. Defaults to the "default" database.', + ) - def handle(self, force, update, **options): + def handle(self, force, update, database, **options): vs = ViewSyncer() - vs.run(force, update) + vs.run(force, update, using=database) diff --git a/django_pgviews/models.py b/django_pgviews/models.py index 73715ae..07c5a81 100644 --- a/django_pgviews/models.py +++ b/django_pgviews/models.py @@ -1,7 +1,7 @@ import logging from django.apps import apps -from django.db import connection +from django.db import connections, DEFAULT_DB_ALIAS from django_pgviews.view import create_view, View, MaterializedView from django_pgviews.signals import view_synced, all_views_synced @@ -10,7 +10,7 @@ class ViewSyncer(object): - def run(self, force, update, **options): + def run(self, force, update, using, **options): self.synced = [] backlog = [] for view_cls in apps.get_models(): @@ -20,14 +20,14 @@ def run(self, force, update, **options): loop = 0 while len(backlog) > 0 and loop < 10: loop += 1 - backlog = self.run_backlog(backlog, force, update) + backlog = self.run_backlog(backlog, force, update, using) if loop >= 10: log.warn("pgviews dependencies hit limit. Check if your model dependencies are correct") else: - all_views_synced.send(sender=None) + all_views_synced.send(sender=None, using=using) - def run_backlog(self, models, force, update): + def run_backlog(self, models, force, update, using=DEFAULT_DB_ALIAS): """Installs the list of models given from the previous backlog If the correct dependent views have not been installed, the view @@ -35,6 +35,7 @@ def run_backlog(self, models, force, update): Eventually we get to a point where all dependencies are sorted. """ + connection = connections[using] backlog = [] for view_cls in models: skip = False @@ -63,6 +64,7 @@ def run_backlog(self, models, force, update): force=force, status=status, has_changed=status not in ("EXISTS", "FORCE_REQUIRED"), + using=using, ) self.synced.append(name) except Exception as exc: diff --git a/django_pgviews/signals.py b/django_pgviews/signals.py index 50d5265..876b9c5 100644 --- a/django_pgviews/signals.py +++ b/django_pgviews/signals.py @@ -1,5 +1,5 @@ from django.dispatch import Signal -view_synced = Signal(providing_args=["update", "force", "status", "has_changed"]) +view_synced = Signal(providing_args=["update", "force", "status", "has_changed", "using"]) all_views_synced = Signal()