Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ForeignKeys in views, make it possible to use a database alias for synchronisation #1

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions django_pgviews/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
12 changes: 11 additions & 1 deletion django_pgviews/management/commands/clear_pgviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
12 changes: 8 additions & 4 deletions django_pgviews/management/commands/sync_pgviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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)
12 changes: 7 additions & 5 deletions django_pgviews/models.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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():
Expand All @@ -20,21 +20,22 @@ 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
will be added to the backlog.

Eventually we get to a point where all dependencies are sorted.
"""
connection = connections[using]
backlog = []
for view_cls in models:
skip = False
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion django_pgviews/signals.py
Original file line number Diff line number Diff line change
@@ -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()
2 changes: 1 addition & 1 deletion django_pgviews/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down