Пример #1
0
    def test_resource_count(self):
        topic_tree_node = tree()
        query = Metadata(topic_tree_node)

        results = query.annotate(**{RESOURCE_COUNT: ResourceCount()})
        serialized = ContentNodeSerializer(topic_tree_node).data

        self.assertEqual(
            serialized.get('metadata').get('resource_count'),
            results.get(serialized.get('id')).get(RESOURCE_COUNT))
        self.assertEqual(5,
                         results.get(serialized.get('id')).get(RESOURCE_COUNT))
Пример #2
0
    def test_descendant_count(self):
        topic_tree_node = tree()
        query = Metadata(topic_tree_node)

        results = query.annotate(**{DESCENDANT_COUNT: DescendantCount()})
        serialized = ContentNodeSerializer(topic_tree_node).data

        self.assertEqual(
            serialized.get('metadata').get('total_count'),
            results.get(serialized.get('id')).get(DESCENDANT_COUNT))
        self.assertEqual(
            7,
            results.get(serialized.get('id')).get(DESCENDANT_COUNT))
Пример #3
0
    def test_coach_count(self):
        topic_tree_node = tree()
        nested_topic = topic_tree_node.get_descendants().filter(
            kind=content_kinds.TOPIC).first()
        self.create_coach_node(nested_topic)

        query = Metadata(topic_tree_node)

        results = query.annotate(**{COACH_COUNT: CoachCount()})
        serialized = ContentNodeSerializer(topic_tree_node).data

        self.assertEqual(
            serialized.get('metadata').get('coach_count'),
            results.get(serialized.get('id')).get(COACH_COUNT))
        self.assertEqual(1, results.get(serialized.get('id')).get(COACH_COUNT))
Пример #4
0
    def test_resource_size__topic(self):
        topic_tree_node = tree()
        nested_topic = topic_tree_node.get_descendants().filter(
            kind=content_kinds.TOPIC).first()
        self.create_coach_node(nested_topic)

        query = Metadata(topic_tree_node)
        results = query.annotate(**{RESOURCE_SIZE: ResourceSize()})
        serialized = ContentNodeSerializer(topic_tree_node).data

        self.assertEqual(
            serialized.get('metadata').get('resource_size'),
            results.get(serialized.get('id')).get(RESOURCE_SIZE))
        self.assertEqual(0,
                         results.get(serialized.get('id')).get(RESOURCE_SIZE))
Пример #5
0
    def test_assessment_count(self):
        tree()
        node = ContentNode.objects.get(
            node_id='00000000000000000000000000000005')
        query = Metadata(node)

        results = query.annotate(**{ASSESSMENT_COUNT: AssessmentCount()})
        serialized = ContentNodeSerializer(node).data

        self.assertEqual(
            serialized.get('metadata').get('resource_count'),
            results.get(serialized.get('id')).get(ASSESSMENT_COUNT))
        self.assertEqual(
            3,
            results.get(serialized.get('id')).get(ASSESSMENT_COUNT))
Пример #6
0
def duplicate_nodes(request):
    logging.debug("Entering the copy_node endpoint")

    if request.method != 'POST':
        return HttpResponseBadRequest(
            "Only POST requests are allowed on this endpoint.")
    else:
        data = json.loads(request.body)

        try:
            nodes = data["nodes"]
            sort_order = data.get("sort_order") or 1
            target_parent = data["target_parent"]
            channel_id = data["channel_id"]
            new_nodes = []

            with transaction.atomic():
                with ContentNode.objects.disable_mptt_updates():
                    for node_data in nodes:
                        new_node = _duplicate_node_bulk(node_data['id'],
                                                        sort_order=sort_order,
                                                        parent=target_parent,
                                                        channel_id=channel_id)
                        new_nodes.append(new_node.pk)
                        sort_order += 1

        except KeyError:
            raise ObjectDoesNotExist(
                "Missing attribute from data: {}".format(data))

        serialized = ContentNodeSerializer(
            ContentNode.objects.filter(pk__in=new_nodes), many=True).data
        return HttpResponse(JSONRenderer().render(serialized))
Пример #7
0
def get_nodes_by_ids(request):
    if request.method == 'POST':
        nodes = ContentNode.objects.prefetch_related('children').prefetch_related('files')\
                .prefetch_related('assessment_items').prefetch_related('tags').filter(pk__in=json.loads(request.body))\
                .defer('node_id', 'original_source_node_id', 'source_node_id', 'content_id', 'original_channel_id', 'source_channel_id', 'source_id', 'source_domain', 'created', 'modified')
        return HttpResponse(JSONRenderer().render(
            ContentNodeSerializer(nodes, many=True).data))
Пример #8
0
def get_nodes_by_ids(request, ids):
    nodes = ContentNode.objects.prefetch_related('children', 'files', 'assessment_items', 'tags')\
                       .filter(pk__in=ids.split(","))\
                       .defer('node_id', 'original_source_node_id', 'source_node_id', 'content_id',
                              'original_channel_id', 'source_channel_id', 'source_id', 'source_domain', 'created', 'modified')
    serializer = ContentNodeSerializer(nodes, many=True)
    return Response(serializer.data)
Пример #9
0
def get_node_path(request):
    if request.method == 'POST':
        data = json.loads(request.body)

        try:
            topic = ContentNode.objects.prefetch_related('children').get(
                node_id=data['topic_id'], tree_id=data['tree_id'])

            if topic.kind_id != content_kinds.TOPIC:
                node =  ContentNode.objects.prefetch_related('files')\
                                            .prefetch_related('assessment_items')\
                                            .prefetch_related('tags').get(node_id=data['topic_id'], tree_id=data['tree_id'])
                nodes = node.get_ancestors(ascending=True)
            else:
                node =  data['node_id'] and ContentNode.objects.prefetch_related('files')\
                                            .prefetch_related('assessment_items')\
                                            .prefetch_related('tags').get(node_id=data['node_id'], tree_id=data['tree_id'])
                nodes = topic.get_ancestors(include_self=True, ascending=True)

            return HttpResponse(
                json.dumps({
                    'path':
                    JSONRenderer().render(
                        ContentNodeSerializer(nodes, many=True).data),
                    'node':
                    node and JSONRenderer().render(
                        ContentNodeEditSerializer(node).data),
                    'parent_node_id':
                    topic.kind_id != content_kinds.TOPIC and node.parent
                    and node.parent.node_id
                }))
        except ObjectDoesNotExist:
            return HttpResponseNotFound(
                "Invalid URL: the referenced content does not exist in this channel."
            )
Пример #10
0
def move_nodes(request):
    logging.debug("Entering the move_nodes endpoint")

    if request.method != 'POST':
        return HttpResponseBadRequest(
            "Only POST requests are allowed on this endpoint.")
    else:
        data = json.loads(request.body)

        try:
            nodes = data["nodes"]
            target_parent = ContentNode.objects.get(pk=data["target_parent"])
            channel_id = data["channel_id"]
            min_order = data.get("min_order") or 0
            max_order = data.get("max_order") or min_order + len(nodes)

        except KeyError:
            return ObjectDoesNotExist(
                "Missing attribute from data: {}".format(data))

        all_ids = []
        with transaction.atomic():
            with ContentNode.objects.delay_mptt_updates():
                for n in nodes:
                    min_order = min_order + float(max_order - min_order) / 2
                    node = ContentNode.objects.get(pk=n['id'])
                    _move_node(node,
                               parent=target_parent,
                               sort_order=min_order,
                               channel_id=channel_id)
                    all_ids.append(n['id'])

        serialized = ContentNodeSerializer(
            ContentNode.objects.filter(pk__in=all_ids), many=True).data
        return HttpResponse(JSONRenderer().render(serialized))
Пример #11
0
def sync_nodes(request):
    logging.debug("Entering the sync_nodes endpoint")

    if request.method != 'POST':
        return HttpResponseBadRequest(
            "Only POST requests are allowed on this endpoint.")
    else:
        data = json.loads(request.body)

        try:
            nodes = data["nodes"]
            channel_id = data['channel_id']

        except KeyError:
            return ObjectDoesNotExist(
                "Missing attribute from data: {}".format(data))

        all_nodes = []
        with transaction.atomic(), ContentNode.objects.delay_mptt_updates():
            for n in nodes:
                node, _ = _sync_node(ContentNode.objects.get(pk=n),
                                     channel_id,
                                     sync_attributes=True,
                                     sync_tags=True,
                                     sync_files=True,
                                     sync_assessment_items=True)
                if node.changed:
                    node.save()
                all_nodes.append(node)
        return HttpResponse(JSONRenderer().render(
            ContentNodeSerializer(all_nodes, many=True).data))
Пример #12
0
def get_node_path(request, topic_id, tree_id, node_id):
    try:
        topic = ContentNode.objects.prefetch_related('children').get(
            node_id__startswith=topic_id, tree_id=tree_id)

        if topic.kind_id != content_kinds.TOPIC:
            node = ContentNode.objects.prefetch_related(
                'files', 'assessment_items',
                'tags').get(node_id__startswith=topic_id, tree_id=tree_id)
            nodes = node.get_ancestors(ascending=True)
        else:
            node = node_id and ContentNode.objects.prefetch_related(
                'files', 'assessment_items', 'tags').get(
                    node_id__startswith=node_id, tree_id=tree_id)
            nodes = topic.get_ancestors(include_self=True, ascending=True)

        return HttpResponse(
            json.dumps({
                'path':
                JSONRenderer().render(
                    ContentNodeSerializer(nodes, many=True).data),
                'node':
                node and JSONRenderer().render(
                    ContentNodeEditSerializer(node).data),
                'parent_node_id':
                topic.kind_id != content_kinds.TOPIC and node.parent
                and node.parent.node_id
            }))
    except ObjectDoesNotExist:
        return HttpResponseNotFound(
            "Invalid URL: the referenced content does not exist in this channel."
        )
Пример #13
0
def duplicate_nodes_task(self,
                         user_id,
                         channel_id,
                         target_parent,
                         node_ids,
                         sort_order=1):
    new_nodes = []
    user = User.objects.get(id=user_id)
    self.progress = 0.0
    self.root_nodes_to_copy = len(node_ids)

    self.progress += 10.0
    self.update_state(state='STARTED', meta={'progress': self.progress})

    with transaction.atomic():
        with ContentNode.objects.disable_mptt_updates():
            for node_id in node_ids:
                new_node = duplicate_node_bulk(node_id,
                                               sort_order=sort_order,
                                               parent=target_parent,
                                               channel_id=channel_id,
                                               user=user,
                                               task_object=self)
                new_nodes.append(new_node.pk)
                sort_order += 1

    return ContentNodeSerializer(ContentNode.objects.filter(pk__in=new_nodes),
                                 many=True).data
Пример #14
0
    def test_fields_are_json_serializable(self):
        """
        The serializer should return data that is ready for serialization, and not in 'object' form.
        """

        node_ids = ['00000000000000000000000000000003', '00000000000000000000000000000004', '00000000000000000000000000000005']
        objects = ContentNodeSerializer(ContentNode.objects.filter(node_id__in=node_ids), many=True).data
        for object in objects:
            ensure_no_querysets_in_serializer(object)
Пример #15
0
    def test_repr_doesnt_evaluate_querysets(self):
        node_ids = [
            "00000000000000000000000000000003",
            "00000000000000000000000000000004",
            "00000000000000000000000000000005",
        ]
        objects = ContentNodeSerializer(
            ContentNode.objects.filter(node_id__in=node_ids), many=True
        )

        object = ContentNodeSerializer(
            ContentNode.objects.get(node_id=node_ids[0])
        )

        # Ensure we don't evaluate querysets when repr is called on a Serializer. See docs for
        # no_field_eval_repr in contentcuration/serializers.py for more info.
        obj_string = repr(object)
        assert "QuerySet" not in obj_string, "object __repr__ contains queryset: {}".format(obj_string)

        objs_string = repr(objects)
        assert "QuerySet" not in objs_string, "objects __repr__ contains queryset: {}".format(objs_string)
Пример #16
0
def duplicate_node_inline(request):
    logging.debug("Entering the copy_node endpoint")

    if request.method != 'POST':
        return HttpResponseBadRequest(
            "Only POST requests are allowed on this endpoint.")
    else:
        data = json.loads(request.body)

        try:

            node = ContentNode.objects.get(pk=data["node_id"])
            channel_id = data["channel_id"]
            target_parent = ContentNode.objects.get(pk=data["target_parent"])
            channel = target_parent.get_channel()
            request.user.can_edit(channel and channel.pk)

            record_node_duplication_stats(
                [node], ContentNode.objects.get(pk=target_parent.pk),
                Channel.objects.get(pk=channel_id))

            new_node = None
            with transaction.atomic():
                with ContentNode.objects.disable_mptt_updates():
                    sort_order = (
                        node.sort_order + node.get_next_sibling().sort_order
                    ) / 2 if node.get_next_sibling() else node.sort_order + 1
                    new_node = _duplicate_node_bulk(node,
                                                    sort_order=sort_order,
                                                    parent=target_parent,
                                                    channel_id=channel_id,
                                                    user=request.user)
                    if not new_node.title.endswith(_(" (Copy)")):
                        new_node.title = new_node.title + _(" (Copy)")
                        new_node.save()

            return HttpResponse(JSONRenderer().render(
                ContentNodeSerializer(
                    ContentNode.objects.filter(pk=new_node.pk),
                    many=True).data))

        except KeyError:
            raise ObjectDoesNotExist(
                "Missing attribute from data: {}".format(data))
Пример #17
0
def duplicate_nodes(request):
    logging.debug("Entering the copy_node endpoint")

    if request.method != 'POST':
        return HttpResponseBadRequest(
            "Only POST requests are allowed on this endpoint.")

    data = json.loads(request.body)

    try:
        nodes = data["nodes"]
        sort_order = data.get("sort_order") or 1
        channel_id = data["channel_id"]
        new_nodes = []
        target_parent = ContentNode.objects.get(pk=data["target_parent"])
        channel = target_parent.get_channel()
        request.user.can_edit(channel and channel.pk)

        nodes_being_copied = []
        for node_data in nodes:
            nodes_being_copied.append(
                ContentNode.objects.get(pk=node_data['id']))
        # record_node_duplication_stats(nodes_being_copied, ContentNode.objects.get(pk=target_parent.pk),
        #                               Channel.objects.get(pk=channel_id))

        with transaction.atomic():
            with ContentNode.objects.disable_mptt_updates():
                for node_data in nodes:
                    new_node = duplicate_node_bulk(node_data['id'],
                                                   sort_order=sort_order,
                                                   parent=target_parent,
                                                   channel_id=channel_id,
                                                   user=request.user)
                    new_nodes.append(new_node.pk)
                    sort_order += 1

    except KeyError:
        raise ObjectDoesNotExist(
            "Missing attribute from data: {}".format(data))

    serialized = ContentNodeSerializer(
        ContentNode.objects.filter(pk__in=new_nodes), many=True).data
    return HttpResponse(JSONRenderer().render(serialized))
Пример #18
0
def sync_channel_endpoint(request):
    logging.debug("Entering the sync_nodes endpoint")

    if request.method != 'POST':
        return HttpResponseBadRequest(
            "Only POST requests are allowed on this endpoint.")
    else:
        data = json.loads(request.body)

        try:
            nodes = sync_channel(
                Channel.objects.get(pk=data['channel_id']),
                sync_attributes=data.get('attributes'),
                sync_tags=data.get('tags'),
                sync_files=data.get('files'),
                sync_assessment_items=data.get('assessment_items'),
                sync_sort_order=data.get('sort'),
            )

            return HttpResponse(JSONRenderer().render(
                ContentNodeSerializer(nodes, many=True).data))
        except KeyError:
            return ObjectDoesNotExist(
                "Missing attribute from data: {}".format(data))