-
Notifications
You must be signed in to change notification settings - Fork 54
signal handlers for syncing of project views and tasks #1218
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
Conversation
d708437 to
9065876
Compare
rdmo/projects/handlers/utils.py
Outdated
| @@ -0,0 +1,10 @@ | |||
|
|
|||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think those methods should exist, this should be inline in the handlers (and without the getattr).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could make it more explicit but it would require a lot more boilerplate code.
The signal handlers for View and Task are basically duplicates, so there would be 18 branches instead of the 9 if action == ... in total in the different functions for .catalogs, .sites and .groups .
But we already agreed about this in the meeting right?
Or would there be an extra use case that would require an update on the Issues as well, when project.tasks are handled?
Example for an explicit function
# Identify the catalogs affected by this change
catalogs = model.objects.filter(pk__in=pk_set)
# Determine the projects to be modified
if action == 'post_add':
projects = Project.objects.filter_catalogs(catalogs).exclude(views=instance)
for project in projects:
project.views.add(instance)
elif action == 'post_remove':
projects = Project.objects.filter_catalogs(catalogs).filter(views=instance)
for project in projects:
project.views.remove(instance)
elif action == 'post_clear':
projects = Project.objects.filter(views=instance)
for project in projects:
project.views.remove(instance)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No I mean just remove_instance_from_projects and add_instance_to_projects should be inlined to the generic handlers.
rdmo/tasks/managers.py
Outdated
| def filter_catalog(self, catalog): | ||
| return self.filter(models.Q(catalogs=None) | models.Q(catalogs=catalog)) | ||
|
|
||
| def filter_available_views_for_project(self, project): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that a Project should be able to find the views that are available for itself. Do you agree and would this query be correct for that?
I've changed the filter_group a little bit to handle a list of users as well as a single user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to check after the meeting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this kind of method is also needed for an endpoint (for project.views) in the new Project Detail in React I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed in the meeting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change filter to filter_for_project_site and filter_project_owners_groups and add project.groups: set()
| if 'cancel' in self.data: | ||
| return self.instance | ||
|
|
||
| # if the catalog is the same, do nothing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to prevent calling the save method if nothing was changed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure, but shouldn't this be handled by the UpdateView... maybe because we use only parts of the model here.
| return | ||
|
|
||
| # Defer synchronization of views | ||
| setattr(instance, DEFERRED_SYNC_TASKS_KEY, True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I needed a pre_save to check if the catalog was changed or not. And afterwards it passes this boolean (with a "deferred" attribute name) to the post_save.
It seems complicated for just a project.save() but could not find another way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove setattr and just use, eg. instance._catalog_has_changed_sync_task
| for catalog in view.catalogs.all(): | ||
| catalog_views_mapping[catalog.id].append({ | ||
| 'id': view.id, | ||
| 'sites': list(view.sites.values_list('id', flat=True)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to explicitly test this filter filter_available_views_for_project with this mapping but have not implemented that test yet.
55905ba to
e19be64
Compare
rdmo/core/managers.py
Outdated
| def filter_group(self, user): | ||
| groups = user.groups.all() | ||
| def filter_group(self, users): | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove newline.
| if 'cancel' in self.data: | ||
| return self.instance | ||
|
|
||
| # if the catalog is the same, do nothing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure, but shouldn't this be handled by the UpdateView... maybe because we use only parts of the model here.
rdmo/projects/forms.py
Outdated
| 'tasks': forms.CheckboxSelectMultiple() | ||
| } | ||
|
|
||
| def save(self, commit=True, *args, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this is just about not saving the instance when nothing changed, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, but it might be just an optional optimization, think I'll remove it again for now.
rdmo/projects/handlers/utils.py
Outdated
| @@ -0,0 +1,10 @@ | |||
|
|
|||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No I mean just remove_instance_from_projects and add_instance_to_projects should be inlined to the generic handlers.
| <th style="width: 15%">{% trans 'Status' %}</th> | ||
| <th style="width: 10%" class="text-right"> | ||
| {% if can_change_project %} | ||
| {% if can_change_project and not settings.PROJECT_TASKS_SYNC %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But only for tasks it seems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, its for both, but there is another error: A view/task without catalog should be available to all projects. Also the update-task/view-for-project forms should be disabled when the setting is True. Check /projects/1/update/views/ and /projects/1/update/tasks/. Maybe 404?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I am adding now a filter to the managers that is used for all cases where a project needs its available views/tasks.
There is no request.user in the loop anymore. Is that a problem? The filter is determined by the project's properties (like project.site, .catalogs and the new .groups )
def filter_available_views_for_project(self, project):
site_filter = Q(sites=project.site) | Q(sites__isnull=True)
catalogs_filter = Q(catalogs=project.catalog) | Q(catalogs__isnull=True)
groups_filter = Q(groups__in=project.groups) | Q(groups__isnull=True)
availability_filter = Q(available=True)
return self.filter(site_filter & catalogs_filter & groups_filter & availability_filter)
rdmo/tasks/managers.py
Outdated
| def filter_catalog(self, catalog): | ||
| return self.filter(models.Q(catalogs=None) | models.Q(catalogs=catalog)) | ||
|
|
||
| def filter_available_views_for_project(self, project): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to check after the meeting.
rdmo/core/settings.py
Outdated
|
|
||
| PROJECT_REMOVE_VIEWS = True | ||
| PROJECT_VIEWS_SYNC = True | ||
| PROJECT_TASKS_SYNC = True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should these actually be enabled by default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think not.
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
# Conflicts: # rdmo/projects/handlers.py
…hange in catalog Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
…bled Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de> # Conflicts: # rdmo/core/settings.py
… handlers Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
…ps to Project Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
4860e95 to
50f25dd
Compare
|
rebased to 2.3.0 |
jochenklar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main issue is about the new managers and availability. An reviewer/editor/admin should be able to assign a non available Task/View to a project to test it.
rdmo/core/settings.py
Outdated
|
|
||
| PROJECT_REMOVE_VIEWS = True | ||
| PROJECT_VIEWS_SYNC = True | ||
| PROJECT_TASKS_SYNC = True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think not.
rdmo/views/managers.py
Outdated
| catalogs_filter = Q(catalogs=project.catalog) | Q(catalogs__isnull=True) | ||
| groups_filter = Q(groups__in=project.groups) | Q(groups__isnull=True) | ||
| availability_filter = Q(available=True) | ||
| return self.filter(site_filter & catalogs_filter & groups_filter & availability_filter) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am sorry but there is a newline in rdmo.tasks.managers right here 🙃
testing/config/settings/base.py
Outdated
| PROJECT_SEND_INVITE = True | ||
|
|
||
| PROJECT_REMOVE_VIEWS = True | ||
| PROJECT_VIEWS_SYNC = True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depending on the default settings and the tests, maybe this should be False (or removed from this file).
rdmo/tasks/managers.py
Outdated
| site_filter = Q(sites=project.site) | Q(sites__isnull=True) | ||
| catalogs_filter = Q(catalogs=project.catalog) | Q(catalogs__isnull=True) | ||
| groups_filter = Q(groups__in=project.groups) | Q(groups__isnull=True) | ||
| availability_filter = Q(available=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you removed the check for the managers and admins here, this was done by .filter_availability(self.request.user) and needs the user. This comes from AvailabilityQuerySetMixin. I think you also reimplemented the other thinks in core/managers.py.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the availability part should stay in AvailabilityQuerySetMixin and we need only filter_for_project and use it like this
tasks = Task.objects.filter_for_project(project).filter_availability(self.request.user)alternatively 3 methods
tasks = Task.objects.filter_for_project_site(project) \
.filter_for_project_catalog(project) \
.filter_for_project_group(project) \
.filter_availability(self.request.user)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, Ive added it now like this in the code where it is already several times indented.
What do you think about this type of notation? ;)
tasks = (
Task.objects
.filter_for_project(project)
.filter_availability(self.request.user)
)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like "my" style better, but I think this is fine (at least no \). I would indent the two '.filter...' lines by 4.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've used one-liner queries when there is only a single filter and it fits on one line, for multiple filters I've used this multi-line parentheses notation with the extra indent. So basically best of both worlds ;)
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
Signed-off-by: David Wallace <david.wallace@tu-darmstadt.de>
jochenklar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks!

Description
For the settings this PR removes:
PROJECT_REMOVE_VIEWS = Trueand adds:
The
projects/handlers.pyare refactored into aproject/handlerspackage with aproject/handlers/generic_handlers.pymodule that contains the logic for signal receivers.It handles the signals for changes in
View.catalogs,View.sites,View.groupsas well asTask.catalogs,Task.sites,Task.groupsand updates theproject.viewsorprojects.tasks.Tests, that only use db
view.catalog.add(...)methods and not the client, are included.Related issues: #966, #1198, #345,
Related PRs: #431, #1200
Motivation and Context
ToBeDone:
How has this been tested?
Screenshots (if appropriate)