def _save(self, tasks): serializer = self.get_serializer(data=tasks, many=True) serializer.is_valid(raise_exception=True) task_instances = serializer.save(project_id=self.kwargs['pk']) project = generics.get_object_or_404(Project.objects.for_user(self.request.user), pk=self.kwargs['pk']) emit_webhooks_for_instance(self.request.user.active_organization, project, WebhookAction.TASKS_CREATED, task_instances) return task_instances, serializer
def delete_tasks_annotations(project, queryset, **kwargs): """ Delete all annotations by tasks ids :param project: project instance :param queryset: filtered tasks db queryset """ task_ids = queryset.values_list('id', flat=True) annotations = Annotation.objects.filter(task__id__in=task_ids) count = annotations.count() # take only tasks where annotations were deleted real_task_ids = set(list(annotations.values_list('task__id', flat=True))) annotations_ids = list(annotations.values('id')) annotations.delete() emit_webhooks_for_instance(project.organization, project, WebhookAction.ANNOTATIONS_DELETED, annotations_ids) start_job_async_or_sync(bulk_update_stats_project_tasks, queryset.filter(is_labeled=True)) request = kwargs['request'] Task.objects.filter(id__in=real_task_ids).update(updated_at=datetime.now(), updated_by=request.user) return { 'processed_items': count, 'detail': 'Deleted ' + str(count) + ' annotations' }
def perform_create(self, serializer): project = get_object_with_check_and_log(self.request, Project, pk=self.kwargs['pk']) instance = serializer.save(project=project) emit_webhooks_for_instance(self.request.user.active_organization, project, WebhookAction.TASKS_CREATED, [instance])
def perform_create(self, serializer): project_id = self.request.data.get('project') generics.get_object_or_404(Project, pk=project_id) project = generics.get_object_or_404(Project, pk=project_id) instance = serializer.save(project=project) emit_webhooks_for_instance(self.request.user.active_organization, project, WebhookAction.TASKS_CREATED, [instance])
def delete(self, request, *args, **kwargs): project = generics.get_object_or_404(Project.objects.for_user( self.request.user), pk=self.kwargs['pk']) task_ids = list(Task.objects.filter(project=project).values('id')) Task.objects.filter(project=project).delete() emit_webhooks_for_instance(request.user.active_organization, None, WebhookAction.TASKS_DELETED, task_ids) return Response(data={'tasks': task_ids}, status=204)
def delete_tasks(project, queryset, **kwargs): """ Delete tasks by ids :param project: project instance :param queryset: filtered tasks db queryset """ tasks_ids = list(queryset.values('id')) count = len(tasks_ids) tasks_ids_list = [task['id'] for task in tasks_ids] # signals to switch off signals = [(post_delete, update_is_labeled_after_removing_annotation, Annotation), (post_delete, update_all_task_states_after_deleting_task, Task), (pre_delete, remove_data_columns, Task), (pre_delete, remove_project_summary_annotations, Annotation)] # delete all project tasks if count == project.tasks.count(): with temporary_disconnect_list_signal(signals): queryset.delete() project.summary.reset() # delete only specific tasks else: # update project summary start_job_async_or_sync(async_project_summary_recalculation, tasks_ids_list, project.id) with temporary_disconnect_list_signal(signals): queryset.delete() project.update_tasks_states(maximum_annotations_changed=False, overlap_cohort_percentage_changed=False, tasks_number_changed=True) # emit webhooks for project emit_webhooks_for_instance(project.organization, project, WebhookAction.TASKS_DELETED, tasks_ids) # remove all tabs if there are no tasks in project reload = False if not project.tasks.exists(): project.views.all().delete() reload = True return { 'processed_items': count, 'reload': reload, 'detail': 'Deleted ' + str(count) + ' tasks' }
def test_emit_webhooks_for_instance(setup_project_dialog, organization_webhook): webhook = organization_webhook project_title = f'Projects 1' project = Project.objects.create(title=project_title) with requests_mock.Mocker(real_http=True) as m: m.register_uri('POST', webhook.url) emit_webhooks_for_instance( webhook.organization, webhook.project, WebhookAction.PROJECT_CREATED, instance=project ) assert len(m.request_history) == 1 assert m.request_history[0].method == 'POST' data = m.request_history[0].json() assert 'action' in data assert 'project' in data assert project_title == data['project']['title']
def predictions_to_annotations(project, queryset, **kwargs): request = kwargs['request'] user = request.user model_version = request.data.get('model_version') queryset = queryset.filter(predictions__isnull=False) predictions = Prediction.objects.filter(task__in=queryset, child_annotations__isnull=True) # model version filter if model_version is not None: if isinstance(model_version, list): predictions = predictions.filter( model_version__in=model_version).distinct() else: predictions = predictions.filter(model_version=model_version) predictions_values = list( predictions.values_list('result', 'model_version', 'task_id', 'id')) # prepare annotations annotations = [] tasks_ids = [] for result, model_version, task_id, prediction_id in predictions_values: tasks_ids.append(task_id) annotations.append({ 'result': result, 'completed_by_id': user.pk, 'task_id': task_id, 'parent_prediction_id': prediction_id }) count = len(annotations) logger.debug(f'{count} predictions will be converter to annotations') db_annotations = [Annotation(**annotation) for annotation in annotations] db_annotations = Annotation.objects.bulk_create(db_annotations) Task.objects.filter(id__in=tasks_ids).update(updated_at=now(), updated_by=request.user) if db_annotations: TaskSerializerBulk.post_process_annotations(db_annotations) # Execute webhook for created annotations emit_webhooks_for_instance(user.active_organization, project, WebhookAction.ANNOTATIONS_CREATED, db_annotations) return {'response_code': 200, 'detail': f'Created {count} annotations'}
def delete_tasks_annotations(project, queryset, **kwargs): """ Delete all annotations by tasks ids :param project: project instance :param queryset: filtered tasks db queryset """ task_ids = queryset.values_list('id', flat=True) annotations = Annotation.objects.filter(task__id__in=task_ids) count = annotations.count() annotations_ids = list(annotations.values('id')) annotations.delete() emit_webhooks_for_instance(project.organization, project, WebhookAction.ANNOTATIONS_DELETED, annotations_ids) return { 'processed_items': count, 'detail': 'Deleted ' + str(count) + ' annotations' }
def delete_tasks(project, queryset, **kwargs): """ Delete tasks by ids :param project: project instance :param queryset: filtered tasks db queryset """ tasks_ids = list(queryset.values('id')) count = len(tasks_ids) # delete all project tasks if count == project.tasks.count(): with temporary_disconnect_all_signals(): queryset.delete() project.summary.reset() project.update_tasks_states(maximum_annotations_changed=False, overlap_cohort_percentage_changed=False, tasks_number_changed=True) # delete only specific tasks else: # this signal re-save the task back with temporary_disconnect_signal( signals.post_delete, update_is_labeled_after_removing_annotation, Annotation): queryset.delete() emit_webhooks_for_instance(project.organization, project, WebhookAction.TASKS_DELETED, tasks_ids) # remove all tabs if there are no tasks in project reload = False if not project.tasks.exists(): project.views.all().delete() reload = True return { 'processed_items': count, 'reload': reload, 'detail': 'Deleted ' + str(count) + ' tasks' }
def create(self, validated_data): ''' Bulk creation objects of Label model with related LabelLink reusing already existing labels ''' from webhooks.utils import emit_webhooks_for_instance with transaction.atomic(): # loading already existing labels titles = [item['title'] for item in validated_data] existing_labels = Label.objects.filter( organization=self.context['request'].user.active_organization, title__in=titles).all() existing_labels_map = { label.title: label for label in existing_labels } # create objects for labels, that we need to create labels_data = [] labels = [] labels_create = [] for item in validated_data: project = item.pop('project') from_name = item.pop('from_name') if item['title'] in existing_labels_map: label = existing_labels_map[item['title']] else: label = Label(**item) labels_create.append(label) labels.append(label) labels_data.append(dict(project=project, from_name=from_name)) if labels_create: if settings.DJANGO_DB == settings.DJANGO_DB_SQLITE: created_labels = {} for label in labels_create: label.save() created_labels[label.title] = label else: created_labels = { label.title: label for label in Label.objects.bulk_create(labels_create) } # connect existing and created labels to project with LabelLink links = [] result = [] for index, label in enumerate(labels): if label.id is None: label = created_labels[label.title] label.project = labels_data[index]['project'] label.from_name = labels_data[index]['from_name'] result.append(label) links.append( LabelLink( **{ 'label': label, 'project': labels_data[index]['project'], 'from_name': labels_data[index]['from_name'], })) links = LabelLink.objects.bulk_create(links, ignore_conflicts=True) # webhooks processing # bulk_create with ignore_conflicts doesn't return ids, reloading links project = labels[0].project label_ids = [label.id for label in result] links = LabelLink.objects.filter(label_id__in=label_ids, project=project).all() if links: emit_webhooks_for_instance( self.context['request'].user.active_organization, links[0].project, 'LABEL_LINK_CREATED', links) return result