-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1218 from rdmorganiser/feat-sync-project-views-an…
…d-tasks signal handlers for syncing of project views and tasks Related issues: #966, #1198, #345, #431
- Loading branch information
Showing
30 changed files
with
846 additions
and
197 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 was deleted.
Oops, something went wrong.
Empty file.
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,110 @@ | ||
from django.contrib.auth.models import Group, User | ||
from django.contrib.sites.models import Site | ||
|
||
from rdmo.projects.models import Membership, Project | ||
from rdmo.questions.models import Catalog | ||
|
||
|
||
def m2m_catalogs_changed_projects_sync_signal_handler(instance, action, pk_set, project_field): | ||
|
||
if action == 'post_remove' and pk_set: | ||
projects_to_change = ( | ||
Project.objects | ||
.filter_catalogs(catalogs=Catalog.objects.filter(pk__in=pk_set)) | ||
.filter(**{project_field: instance}) | ||
) | ||
for project in projects_to_change: # remove instance from project | ||
getattr(project, project_field).remove(instance) | ||
|
||
elif action == 'post_clear': | ||
projects_to_change = Project.objects.filter(**{project_field: instance}) | ||
for project in projects_to_change: # remove instance from project | ||
getattr(project, project_field).remove(instance) | ||
|
||
elif action == 'post_add' and pk_set: | ||
projects_to_change = ( | ||
Project.objects | ||
.filter_catalogs(catalogs=Catalog.objects.filter(pk__in=pk_set)) | ||
.exclude(**{project_field: instance}) | ||
) | ||
for project in projects_to_change: # add instance to project | ||
getattr(project, project_field).add(instance) | ||
|
||
|
||
def m2m_sites_changed_projects_sync_signal_handler(instance, action, pk_set, project_field): | ||
|
||
if action == 'post_remove' and pk_set: | ||
projects_to_change = ( | ||
Project.objects | ||
.filter_catalogs(catalogs=instance.catalogs.all()) | ||
.filter(site__in=Site.objects.filter(pk__in=pk_set)) | ||
.filter(**{project_field: instance}) | ||
) | ||
for project in projects_to_change: # remove instance from project | ||
getattr(project, project_field).remove(instance) | ||
|
||
elif action == 'post_clear': | ||
projects_to_change = ( | ||
Project.objects | ||
.filter_catalogs() | ||
.filter(**{project_field: instance}) | ||
) | ||
for project in projects_to_change: # remove instance from project | ||
getattr(project, project_field).remove(instance) | ||
|
||
elif action == 'post_add' and pk_set: | ||
projects_to_change = ( | ||
Project.objects | ||
.filter_catalogs(catalogs=instance.catalogs.all()) | ||
.filter(site__in=Site.objects.filter(pk__in=pk_set)) | ||
.exclude(**{project_field: instance}) | ||
) | ||
for project in projects_to_change: # add instance to project | ||
getattr(project, project_field).add(instance) | ||
|
||
|
||
def m2m_groups_changed_projects_sync_signal_handler(instance, action, pk_set, project_field): | ||
|
||
if action == 'post_remove' and pk_set: | ||
related_groups = Group.objects.filter(pk__in=pk_set) | ||
users = User.objects.filter(groups__in=related_groups) | ||
memberships = ( | ||
Membership.objects | ||
.filter(role='owner', user__in=users) | ||
.values_list('id', flat=True) | ||
) | ||
projects_to_change = ( | ||
Project.objects | ||
.filter_catalogs(catalogs=instance.catalogs.all()) | ||
.filter(memberships__in=memberships) | ||
.filter(**{project_field: instance}) | ||
) | ||
for project in projects_to_change: # remove instance from project | ||
getattr(project, project_field).remove(instance) | ||
|
||
elif action == 'post_clear': | ||
# Remove all linked projects regardless of catalogs | ||
projects_to_change = ( | ||
Project.objects | ||
.filter_catalogs() | ||
.filter(**{project_field: instance}) | ||
) | ||
for project in projects_to_change: # remove instance from project | ||
getattr(project, project_field).remove(instance) | ||
|
||
elif action == 'post_add' and pk_set: | ||
related_groups = Group.objects.filter(pk__in=pk_set) | ||
users = User.objects.filter(groups__in=related_groups) | ||
memberships = ( | ||
Membership.objects | ||
.filter(role='owner', user__in=users) | ||
.values_list('id', flat=True) | ||
) | ||
projects_to_change = ( | ||
Project.objects | ||
.filter_catalogs(catalogs=instance.catalogs.all()) | ||
.filter(memberships__in=memberships) | ||
.exclude(**{project_field: instance}) | ||
) | ||
for project in projects_to_change: # add instance to project | ||
getattr(project, project_field).add(instance) |
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,25 @@ | ||
from django.db.models.signals import m2m_changed | ||
from django.dispatch import receiver | ||
|
||
from rdmo.tasks.models import Task | ||
|
||
from .generic_handlers import ( | ||
m2m_catalogs_changed_projects_sync_signal_handler, | ||
m2m_groups_changed_projects_sync_signal_handler, | ||
m2m_sites_changed_projects_sync_signal_handler, | ||
) | ||
|
||
|
||
@receiver(m2m_changed, sender=Task.catalogs.through) | ||
def m2m_changed_task_catalog_signal(sender, instance, action, pk_set, **kwargs): | ||
m2m_catalogs_changed_projects_sync_signal_handler(instance, action, pk_set, 'tasks') | ||
|
||
|
||
@receiver(m2m_changed, sender=Task.sites.through) | ||
def m2m_changed_task_sites_signal(sender, instance, action, pk_set, **kwargs): | ||
m2m_sites_changed_projects_sync_signal_handler(instance, action, pk_set, 'tasks') | ||
|
||
|
||
@receiver(m2m_changed, sender=Task.groups.through) | ||
def m2m_changed_task_groups_signal(sender, instance, action, pk_set, **kwargs): | ||
m2m_groups_changed_projects_sync_signal_handler(instance, action, pk_set, 'tasks') |
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,25 @@ | ||
from django.db.models.signals import m2m_changed | ||
from django.dispatch import receiver | ||
|
||
from rdmo.views.models import View | ||
|
||
from .generic_handlers import ( | ||
m2m_catalogs_changed_projects_sync_signal_handler, | ||
m2m_groups_changed_projects_sync_signal_handler, | ||
m2m_sites_changed_projects_sync_signal_handler, | ||
) | ||
|
||
|
||
@receiver(m2m_changed, sender=View.catalogs.through) | ||
def m2m_changed_view_catalog_signal(sender, instance, action, pk_set, **kwargs): | ||
m2m_catalogs_changed_projects_sync_signal_handler(instance, action, pk_set, 'views') | ||
|
||
|
||
@receiver(m2m_changed, sender=View.sites.through) | ||
def m2m_changed_view_sites_signal(sender, instance, action, pk_set, **kwargs): | ||
m2m_sites_changed_projects_sync_signal_handler(instance, action, pk_set, 'views') | ||
|
||
|
||
@receiver(m2m_changed, sender=View.groups.through) | ||
def m2m_changed_view_groups_signal(sender, instance, action, pk_set, **kwargs): | ||
m2m_groups_changed_projects_sync_signal_handler(instance, action, pk_set, 'views') |
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,36 @@ | ||
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 | ||
|
||
|
||
@receiver(pre_save, sender=Project) | ||
def pre_save_project_sync_tasks_from_catalog(sender, instance, raw, update_fields, **kwargs): | ||
instance._catalog_has_changed_sync_tasks = False | ||
|
||
if raw or (update_fields and 'catalog' not in update_fields): | ||
return | ||
|
||
if instance.id is not None: | ||
# Fetch the original catalog from the database | ||
if sender.objects.get(id=instance.id).catalog == instance.catalog: | ||
# Do nothing if the catalog has not changed | ||
return | ||
|
||
# Defer synchronization of views | ||
instance._catalog_has_changed_sync_tasks = True | ||
|
||
|
||
@receiver(post_save, sender=Project) | ||
def post_save_project_sync_tasks_from_catalog(sender, instance, created, raw, update_fields, **kwargs): | ||
if raw or (update_fields and 'catalog' not in update_fields): | ||
return | ||
|
||
if instance._catalog_has_changed_sync_tasks or (created and not instance.tasks.exists) : | ||
instance.tasks.set( | ||
Task.objects | ||
.filter_for_project(instance) | ||
.filter(available=True) | ||
.values_list('id', flat=True) | ||
) |
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,36 @@ | ||
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 | ||
|
||
|
||
@receiver(pre_save, sender=Project) | ||
def pre_save_project_sync_views_from_catalog(sender, instance, raw, update_fields, **kwargs): | ||
instance._catalog_has_changed_sync_views = False | ||
|
||
if raw or (update_fields and 'catalog' not in update_fields): | ||
return | ||
|
||
if instance.id is not None: | ||
# Fetch the original catalog from the database | ||
if sender.objects.get(id=instance.id).catalog == instance.catalog: | ||
# Do nothing if the catalog has not changed | ||
return | ||
|
||
# Defer synchronization of views | ||
instance._catalog_has_changed_sync_views = True | ||
|
||
|
||
@receiver(post_save, sender=Project) | ||
def post_save_project_sync_views_from_catalog(sender, instance, created, raw, update_fields, **kwargs): | ||
if raw or (update_fields and 'catalog' not in update_fields): | ||
return | ||
|
||
if instance._catalog_has_changed_sync_views or (created and not instance.views.exists): | ||
instance.views.set( | ||
View.objects | ||
.filter_for_project(instance) | ||
.filter(available=True) | ||
.values_list('id', flat=True) | ||
) |
Oops, something went wrong.