-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(project, handlers): refactor and add handler for project save, c…
…hange in catalog Signed-off-by: David Wallace <[email protected]>
- Loading branch information
Showing
14 changed files
with
210 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from django.db.models.signals import post_save, pre_save | ||
from django.dispatch import receiver | ||
|
||
from rdmo.projects.models import Project | ||
from rdmo.tasks.models import Task | ||
|
||
DEFERRED_SYNC_TASKS_KEY = '_deferred_sync_tasks' | ||
|
||
@receiver(pre_save, sender=Project) | ||
def pre_save_project_sync_tasks_from_catalog(sender, instance, raw, update_fields, **kwargs): | ||
if raw or (update_fields and 'catalog' not in update_fields): | ||
return | ||
|
||
# Fetch the original catalog from the database | ||
original_instance = sender.objects.get(id=instance.id) | ||
if original_instance.catalog == instance.catalog: | ||
# Do nothing if the catalog has not changed | ||
return | ||
|
||
# Defer synchronization of views | ||
setattr(instance, DEFERRED_SYNC_TASKS_KEY, True) | ||
|
||
@receiver(post_save, sender=Project) | ||
def post_save_project_sync_tasks_from_catalog(sender, instance, created, raw, **kwargs): | ||
if getattr(instance, DEFERRED_SYNC_TASKS_KEY, None) or (created and not raw): | ||
# For existing projects with catalog changes, use deferred views | ||
instance.views.set(Task.objects.filter_available_tasks_for_project(instance)) | ||
delattr(instance, DEFERRED_SYNC_TASKS_KEY) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from django.db.models.signals import post_save, pre_save | ||
from django.dispatch import receiver | ||
|
||
from rdmo.projects.models import Project | ||
from rdmo.views.models import View | ||
|
||
DEFERRED_SYNC_VIEWS_KEY = '_deferred_sync_views' | ||
|
||
@receiver(pre_save, sender=Project) | ||
def pre_save_project_sync_views_from_catalog(sender, instance, raw, update_fields, **kwargs): | ||
if raw or (update_fields and 'catalog' not in update_fields): | ||
return | ||
|
||
# Fetch the original catalog from the database | ||
original_instance = sender.objects.get(id=instance.id) | ||
if original_instance.catalog == instance.catalog: | ||
# Do nothing if the catalog has not changed | ||
return | ||
|
||
# Defer synchronization of views | ||
setattr(instance, DEFERRED_SYNC_VIEWS_KEY, True) | ||
|
||
@receiver(post_save, sender=Project) | ||
def post_save_project_sync_views_from_catalog(sender, instance, created, raw, update_fields, **kwargs): | ||
if getattr(instance, DEFERRED_SYNC_VIEWS_KEY, None) or (created and not raw): | ||
# For existing projects with catalog changes, use deferred views | ||
instance.views.set(View.objects.filter_available_views_for_project(instance)) | ||
delattr(instance, DEFERRED_SYNC_VIEWS_KEY) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,36 @@ | ||
from collections import defaultdict | ||
|
||
from rdmo.questions.models import Catalog | ||
from rdmo.views.models import View | ||
|
||
|
||
def assert_other_projects_unchanged(other_projects, initial_tasks_state): | ||
for other_project in other_projects: | ||
assert set(other_project.tasks.values_list('id', flat=True)) == set(initial_tasks_state[other_project.id]) | ||
|
||
|
||
|
||
def get_catalog_view_mapping(): | ||
""" | ||
Generate a mapping of catalogs to their associated views. | ||
Includes all catalogs, even those with no views, and adds `sites` and `groups` for each view. | ||
""" | ||
# Initialize an empty dictionary for the catalog-to-views mapping | ||
catalog_views_mapping = defaultdict(list) | ||
|
||
# Populate the mapping for all catalogs | ||
for catalog in Catalog.objects.all(): | ||
catalog_views_mapping[catalog.id] = [] | ||
|
||
# Iterate through all views and enrich the mapping | ||
for view in View.objects.prefetch_related('sites', 'groups'): | ||
if view.catalogs.exists(): # Only include views with valid catalogs | ||
for catalog in view.catalogs.all(): | ||
catalog_views_mapping[catalog.id].append({ | ||
'id': view.id, | ||
'sites': list(view.sites.values_list('id', flat=True)), | ||
'groups': list(view.groups.values_list('id', flat=True)) | ||
}) | ||
|
||
# Convert defaultdict to a regular dictionary | ||
return dict(catalog_views_mapping) |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from rdmo.projects.models import Project | ||
from rdmo.questions.models import Catalog | ||
from rdmo.views.models import View | ||
|
||
from .helpers import get_catalog_view_mapping | ||
|
||
project_id = 10 | ||
|
||
|
||
def test_project_views_sync_when_changing_the_catalog_on_a_project(db, settings): | ||
assert settings.PROJECT_VIEWS_SYNC | ||
|
||
# Setup: Create a catalog, a view, and a project using the catalog | ||
project = Project.objects.get(id=project_id) | ||
initial_project_views = set(project.views.values_list('id', flat=True)) | ||
assert initial_project_views == {1,2,3} # from the fixture | ||
|
||
catalog_view_mapping = get_catalog_view_mapping() | ||
for catalog_id, view_ids in catalog_view_mapping.items(): | ||
if project.catalog_id == catalog_id: | ||
continue # catalog will not change | ||
project.catalog = Catalog.objects.get(id=catalog_id) | ||
project.save() | ||
|
||
# TODO this filter_available_views_for_project method needs to tested explicitly | ||
available_views = set(View.objects | ||
.filter_available_views_for_project(project) | ||
.values_list('id', flat=True) | ||
) | ||
assert set(project.views.values_list('id', flat=True)) == available_views |
Oops, something went wrong.