Пример #1
0
def get_data_view( request, data_view_id ):
    """ Returns a rendered template for the given view.
    """
    # Load the template
    dv = get_object_or_404(DataView, pk=data_view_id)
    code_type = dv.data_view_type.code_type
    template = loader.get_template( "catmaid/" + code_type + ".html" )
    # Get project information and pass all to the template context
    config = json.loads( dv.config )

    # Get all the projects that are visible for the current user
    projects = get_project_qs_for_user(request.user)

    # If requested, filter projects by tags. Otherwise, get all.
    if "filter_tags" in config:
        filter_tags = config["filter_tags"]
        # Only get projects that have all the filter tags set
        projects = projects.filter( tags__name__in=filter_tags ).annotate(
            repeat_count=Count("id") ).filter( repeat_count=len(filter_tags) )

    # Build a stack index
    stacks = list(Stack.objects.all())
    stack_index = dict([(s.id, s) for s in stacks])
    stacks_of = defaultdict(list)
    for pid, sid in ProjectStack.objects.filter(project__in=projects) \
            .order_by('stack__id').values_list('project_id', 'stack_id'):
        stacks_of[pid].append(stack_index[sid])

    # Extend the project list with additional information like editabilty
    projects = extend_projects( request.user, projects )

    # Sort by default
    if "sort" not in config or config["sort"] == True:
        projects = natural_sort( projects, "title" )

    # Build project index
    project_index = dict([(p.id, p) for p in projects])
    project_ids = set(project_index.keys())

    # Build tag index
    ct = ContentType.objects.get_for_model(Project)
    tag_links = TaggedItem.objects.filter(content_type=ct) \
        .values_list('object_id', 'tag__name')
    tag_index = defaultdict(set)
    for pid, t in tag_links:
        if pid in project_ids:
            tag_index[t].add(pid)

    context = Context({
        'data_view': dv,
        'projects': projects,
        'config': config,
        'settings': settings,
        'tag_index': tag_index,
        'project_index': project_index,
        'stack_index': stack_index,
        'stacks_of': stacks_of,
    })

    return HttpResponse( template.render( context ) );
Пример #2
0
def get_data_view( request, data_view_id ):
    """ Returns a rendered template for the given view.
    """
    # Load the template
    dv = get_object_or_404(DataView, pk=data_view_id)
    code_type = dv.data_view_type.code_type
    template = loader.get_template( "catmaid/" + code_type + ".html" )
    # Get project information and pass all to the template context
    config = json.loads( dv.config )

    # Get all the projects that are visible for the current user
    projects = get_project_qs_for_user(request.user)

    # If requested, filter projects by tags. Otherwise, get all.
    if "filter_tags" in config:
        filter_tags = config["filter_tags"]
        # Only get projects that have all the filter tags set
        projects = projects.filter( tags__name__in=filter_tags ).annotate(
            repeat_count=Count("id") ).filter( repeat_count=len(filter_tags) )

    # Extend the project list with additional information like editabilty
    projects = extend_projects( request.user, projects )

    # Sort by default
    if "sort" not in config or config["sort"] == True:
        projects = natural_sort( projects, "title" )

    context = Context({
        'data_view': dv,
        'projects': projects,
        'config': config,
        'settings': settings
    })

    return HttpResponse( template.render( context ) );
Пример #3
0
def get_data_view(request, data_view_id):
    """ Returns a rendered template for the given view.
    """
    # Load the template
    dv = get_object_or_404(DataView, pk=data_view_id)
    code_type = dv.data_view_type.code_type
    template = loader.get_template("catmaid/" + code_type + ".html")
    # Get project information and pass all to the template context
    config = json.loads(dv.config)

    # Get all the projects that are visible for the current user
    projects = get_project_qs_for_user(request.user)

    # If requested, filter projects by tags. Otherwise, get all.
    if "filter_tags" in config:
        filter_tags = config["filter_tags"]
        # Only get projects that have all the filter tags set
        projects = projects.filter(tags__name__in=filter_tags).annotate(
            repeat_count=Count("id")).filter(repeat_count=len(filter_tags))

    # Extend the project list with additional information like editabilty
    projects = extend_projects(request.user, projects)

    # Sort by default
    if "sort" not in config or config["sort"] == True:
        projects = natural_sort(projects, "title")

    context = Context({
        'data_view': dv,
        'projects': projects,
        'config': config,
        'settings': settings
    })

    return HttpResponse(template.render(context))
Пример #4
0
    def test_project_export(self):
        """Test projects/export endpoint, which returns a YAML format which can
        also be understood by the importer.
        """
        # Check that, pre-authentication, we can see none of the
        # projects:
        response = self.client.get('/projects/export')
        self.assertEqual(response.status_code, 200)
        result = json.loads(response.content)
        self.assertEqual(len(result), 0)

        # Now log in and check that we see a different set of projects:
        self.fake_authentication()

        # Add permission to the test user to browse three projects
        test_user = User.objects.get(pk=self.test_user_id)
        valid_project_ids = (1,2,3,5)
        for pid in valid_project_ids:
            p = Project.objects.get(pk=pid)
            assign_perm('can_browse', test_user, p)

        visible_projects = project.get_project_qs_for_user(test_user)

        response = self.client.get('/projects/export')
        self.assertEqual(response.status_code, 200)
        result = yaml.load(response.content)

        # Expect a returned list with four projects
        self.assertEqual(len(result), 4)

        seen_projects = []
        for exported_project in result:
            data = exported_project['project']
            pid = data['id']
            self.assertTrue(pid in valid_project_ids)
            self.assertFalse(pid in seen_projects)
            seen_projects.append(pid)

            p = Project.objects.get(id=pid)
            self.assertEqual(p.title, data['title'])

            stacks = p.stacks.all()
            valid_stack_ids = [s.id for s in stacks]

            stackgroup_links = StackStackGroup.objects.filter(stack__in=stacks)
            valid_stackgroup_ids = [sgl.stack_group_id for sgl in stackgroup_links]

            seen_stacks = []
            seen_stackgroups = []
            for s in data.get('stacks', []):
                stack_id = s['id']
                self.assertIn(stack_id, valid_stack_ids)
                self.assertNotIn(stack_id, seen_stacks)
                seen_stacks.append(stack_id)

                # Compare stacks
                stack = Stack.objects.get(id=stack_id)
                self.assertEqual(stack.title, s['title'])
                self.assertEqual(literal_eval(unicode(stack.dimension)),
                        literal_eval(s['dimension']))
                self.assertEqual(literal_eval(unicode(stack.resolution)),
                        literal_eval(s['resolution']))
                self.assertEqual(stack.num_zoom_levels, s['zoomlevels'])
                self.assertEqual(stack.metadata, s['metadata'])
                self.assertEqual(stack.comment, s['comment'])
                self.assertEqual(stack.attribution, s['attribution'])
                self.assertEqual(stack.description, s['description'])
                self.assertEqual(literal_eval(unicode(stack.canary_location)),
                        literal_eval(s['canary_location']))
                self.assertEqual(literal_eval(unicode(stack.placeholder_color)),
                        literal_eval(s['placeholder_color']))

                # Get all stack mirrors for this stack
                stack_mirrors = StackMirror.objects.filter(stack_id=stack_id).order_by('position')
                self.assertEqual(len(stack_mirrors), len(s['mirrors']))

                # Expect exported stack mirros to be ordered by position
                for sm, sm_export in zip(stack_mirrors, s['mirrors']):
                    # Compare stack mirrors
                    self.assertEqual(sm.image_base, sm_export['url'])
                    self.assertEqual(sm.tile_width, sm_export['tile_width'])
                    self.assertEqual(sm.tile_height, sm_export['tile_height'])
                    self.assertEqual(sm.tile_source_type, sm_export['tile_source_type'])
                    self.assertEqual(sm.file_extension, sm_export['fileextension'])

                for sge in s.get('stackgroups', []):
                    sg_id = sge['id']
                    self.assertIn(sg_id, valid_stackgroup_ids)
                    self.assertNotIn(sg_id, seen_stackgroups)
                    seen_stackgroups.append(sg_id)

                    sg = StackGroup.objects.get(id=sg_id)
                    sg_link = StackStackGroup.objects.get(
                        stack=stack, stack_group=sg)
                    self.assertEqual(sg.title, sge['title'])
                    self.assertEqual(sg_link.group_relation.name, sge['relation'])

                # Make sure we have seen all relevant stack groups
                self.assertItemsEqual(valid_stackgroup_ids, seen_stackgroups)

            # Make sure we have seen all relevant stacks
            self.assertItemsEqual(valid_stack_ids, seen_stacks)

        self.assertItemsEqual(valid_project_ids, seen_projects)
Пример #5
0
def get_data_view(request, data_view_id):
    """ Returns a rendered template for the given view.
    """
    # Load the template
    dv = get_object_or_404(DataView, pk=data_view_id)
    code_type = dv.data_view_type.code_type
    template = loader.get_template("catmaid/" + code_type + ".html")
    # Get project information and pass all to the template context
    config = json.loads(dv.config)

    # Get all the projects that are visible for the current user
    projects = get_project_qs_for_user(request.user)

    # If requested, filter projects by tags. Otherwise, get all.
    if "filter_tags" in config:
        filter_tags = config["filter_tags"]
        # Only get projects that have all the filter tags set
        # TODO: Improve performande by not using an IN query (but a temp table
        # join) over all filter_tags.
        projects = projects.filter(tags__name__in=filter_tags).annotate(
            repeat_count=Count("id")).filter(repeat_count=len(filter_tags))

    show_stacks = config.get('show_stacks', True)
    show_stackgroups = config.get('show_stackgroups', True)
    show_mirrors = config.get('show_mirrors', True)

    # Make sure we get all needed stacks in the first query
    if show_stacks:
        projects = projects.prefetch_related('stacks')

    # Build a stack index
    stack_index = defaultdict(list)
    stacks_of = defaultdict(list)
    stack_set_of = defaultdict(set)
    projects_of_stack = defaultdict(set)

    if show_stacks:
        for p in projects:
            stacks = p.stacks.all()
            if show_mirrors:
                stacks = stacks.prefetch_related('stackmirror_set')
            for s in stacks:
                stack_index[s.id] = s
                stacks_of[p.id].append(s)
                if show_stackgroups:
                    stack_set_of[p.id].add(s.id)
                    projects_of_stack[s.id].add(p.id)

    # Build a stack group index, if stack groups should be made available
    stackgroup_index = {}
    stackgroups_of = defaultdict(list)
    if show_stackgroups:
        stackgroup_links = StackStackGroup.objects.all().prefetch_related(
            'stack', 'stack_group')
        stackgroup_members = defaultdict(set)
        for sgl in stackgroup_links:
            stackgroup_index[sgl.stack_group_id] = sgl.stack_group
            stackgroup_members[sgl.stack_group_id].add(sgl.stack.id)
        for sg, members in six.iteritems(stackgroup_members):
            # Only accept stack groups of which all member stacks are linked to
            # the same project.
            member_project_ids = set()
            project_member_ids = defaultdict(set)
            for m in members:
                project_ids = projects_of_stack.get(m, [])
                member_project_ids.update(project_ids)
                for pid in project_ids:
                    project_member_ids[pid].add(m)
            # Find projects where all stacks are linked to
            for p in member_project_ids:
                project_members = project_member_ids[p]
                # If the stack group members in this project are all stack group
                # members, this stack group is available to the project
                if not members.difference(project_members):
                    stackgroups_of[p].append(stackgroup_index[sg])

    # Extend the project list with catalogue information
    if 'catalogue_link' in config:
        projects = add_catalogue_info(request.user, projects)

    # Sort by default
    if "sort" not in config or config["sort"] is True:
        projects = natural_sort(projects, "title")

    # Build project index
    project_index = dict([(p.id, p) for p in projects])
    project_ids = set(project_index.keys())

    # Build tag index
    ct = ContentType.objects.get_for_model(Project)
    tag_links = TaggedItem.objects.filter(content_type=ct) \
        .values_list('object_id', 'tag__name')
    tag_index = defaultdict(set)
    for pid, t in tag_links:
        if pid in project_ids:
            tag_index[t].add(pid)

    context = {
        'data_view': dv,
        'projects': projects,
        'config': config,
        'settings': settings,
        'tag_index': tag_index,
        'project_index': project_index,
        'stack_index': stack_index,
        'stacks_of': stacks_of,
        'stackgroup_index': stackgroup_index,
        'stackgroups_of': stackgroups_of,
        'STATIC_URL': settings.STATIC_URL,
    }

    return HttpResponse(template.render(context))
Пример #6
0
def get_data_view( request, data_view_id ):
    """ Returns a rendered template for the given view.
    """
    # Load the template
    dv = get_object_or_404(DataView, pk=data_view_id)
    code_type = dv.data_view_type.code_type
    template = loader.get_template( "catmaid/" + code_type + ".html" )
    # Get project information and pass all to the template context
    config = json.loads( dv.config )

    # Get all the projects that are visible for the current user
    projects = get_project_qs_for_user(request.user)

    # If requested, filter projects by tags. Otherwise, get all.
    if "filter_tags" in config:
        filter_tags = config["filter_tags"]
        # Only get projects that have all the filter tags set
        # TODO: Improve performande by not using an IN query (but a temp table
        # join) over all filter_tags.
        projects = projects.filter( tags__name__in=filter_tags ).annotate(
            repeat_count=Count("id") ).filter( repeat_count=len(filter_tags) )

    show_stacks = config.get('show_stacks', True)
    show_stackgroups = config.get('show_stackgroups', True)
    show_mirrors = config.get('show_mirrors', True)

    # Make sure we get all needed stacks in the first query
    if show_stacks or show_stackgroups:
        projects = projects.prefetch_related('stacks')

    # Build a stack index
    stack_index = defaultdict(list)
    stacks_of = defaultdict(list)
    stack_set_of = defaultdict(set)
    projects_of_stack = defaultdict(set)

    if show_stacks or show_stackgroups:
        for p in projects:
            stacks = p.stacks.all()
            if show_mirrors:
                stacks = stacks.prefetch_related('stackmirror_set')
            for s in stacks:
                stack_index[s.id] = s
                stacks_of[p.id].append(s)
                if show_stackgroups:
                    stack_set_of[p.id].add(s.id)
                    projects_of_stack[s.id].add(p.id)

    # Build a stack group index, if stack groups should be made available
    stackgroup_index = {}
    stackgroups_of = defaultdict(list)
    if show_stackgroups:
        stackgroup_links = StackStackGroup.objects.all().prefetch_related('stack', 'stack_group')
        stackgroup_members = defaultdict(set)
        for sgl in stackgroup_links:
            stackgroup_index[sgl.stack_group_id] = sgl.stack_group
            stackgroup_members[sgl.stack_group_id].add(sgl.stack.id)
        for sg, members in six.iteritems(stackgroup_members):
            # Only accept stack groups of which all member stacks are linked to
            # the same project.
            member_project_ids = set()
            project_member_ids = defaultdict(set)
            for m in members:
                project_ids = projects_of_stack.get(m, [])
                member_project_ids.update(project_ids)
                for pid in project_ids:
                    project_member_ids[pid].add(m)
            # Find projects where all stacks are linked to
            for p in member_project_ids:
                project_members = project_member_ids[p]
                # If the stack group members in this project are all stack group
                # members, this stack group is available to the project
                if not members.difference(project_members):
                    stackgroups_of[p].append(stackgroup_index[sg])

    # Extend the project list with catalogue information
    if 'catalogue_link' in config:
        projects = add_catalogue_info( request.user, projects )

    # Sort by default
    if "sort" not in config or config["sort"] is True:
        projects = natural_sort( projects, "title" )

    # Build project index
    project_index = dict([(p.id, p) for p in projects])
    project_ids = set(project_index.keys())

    # Build tag index
    ct = ContentType.objects.get_for_model(Project)
    tag_links = TaggedItem.objects.filter(content_type=ct) \
        .values_list('object_id', 'tag__name')
    tag_index = defaultdict(set)
    for pid, t in tag_links:
        if pid in project_ids:
            tag_index[t].add(pid)

    context = {
        'data_view': dv,
        'projects': projects,
        'config': config,
        'settings': settings,
        'tag_index': tag_index,
        'project_index': project_index,
        'stack_index': stack_index,
        'stacks_of': stacks_of,
        'stackgroup_index': stackgroup_index,
        'stackgroups_of': stackgroups_of,
        'STATIC_URL': settings.STATIC_URL,
    }

    return HttpResponse( template.render( context ) )
Пример #7
0
    def test_project_export(self):
        """Test projects/export endpoint, which returns a YAML format which can
        also be understood by the importer.
        """
        # Check that, pre-authentication, we can see none of the
        # projects:
        response = self.client.get('/projects/export')
        self.assertEqual(response.status_code, 200)
        result = json.loads(response.content.decode('utf-8'))
        self.assertEqual(len(result), 0)

        # Now log in and check that we see a different set of projects:
        self.fake_authentication()

        # Add permission to the test user to browse three projects
        test_user = User.objects.get(pk=self.test_user_id)
        valid_project_ids = (1,2,3,5)
        for pid in valid_project_ids:
            p = Project.objects.get(pk=pid)
            assign_perm('can_browse', test_user, p)

        visible_projects = project.get_project_qs_for_user(test_user)

        response = self.client.get('/projects/export')
        self.assertEqual(response.status_code, 200)
        result = yaml.load(response.content.decode('utf-8'))

        # Expect a returned list with four projects
        self.assertEqual(len(result), 4)

        seen_projects = []
        for exported_project in result:
            data = exported_project['project']
            pid = data['id']
            self.assertTrue(pid in valid_project_ids)
            self.assertFalse(pid in seen_projects)
            seen_projects.append(pid)

            p = Project.objects.get(id=pid)
            self.assertEqual(p.title, data['title'])

            stacks = p.stacks.all()
            valid_stack_ids = [s.id for s in stacks]

            stackgroup_links = StackStackGroup.objects.filter(stack__in=stacks)
            valid_stackgroup_ids = [sgl.stack_group_id for sgl in stackgroup_links]

            seen_stacks = []
            seen_stackgroups = []
            for s in data.get('stacks', []):
                stack_id = s['id']
                self.assertIn(stack_id, valid_stack_ids)
                self.assertNotIn(stack_id, seen_stacks)
                seen_stacks.append(stack_id)

                # Compare stacks
                stack = Stack.objects.get(id=stack_id)
                self.assertEqual(stack.title, s['title'])
                self.assertEqual(literal_eval(str(stack.dimension)),
                        literal_eval(s['dimension']))
                self.assertEqual(literal_eval(str(stack.resolution)),
                        literal_eval(s['resolution']))
                self.assertEqual(stack.downsample_factors, s['downsample_factors'])
                self.assertEqual(stack.metadata, s['metadata'])
                self.assertEqual(stack.comment, s['comment'])
                self.assertEqual(stack.attribution, s['attribution'])
                self.assertEqual(stack.description, s['description'])
                self.assertEqual(literal_eval(str(stack.canary_location)),
                        literal_eval(s['canary_location']))
                self.assertEqual(literal_eval(str(stack.placeholder_color)),
                        literal_eval(s['placeholder_color']))

                # Get all stack mirrors for this stack
                stack_mirrors = StackMirror.objects.filter(stack_id=stack_id).order_by('position')
                self.assertEqual(len(stack_mirrors), len(s['mirrors']))

                # Expect exported stack mirros to be ordered by position
                for sm, sm_export in zip(stack_mirrors, s['mirrors']):
                    # Compare stack mirrors
                    self.assertEqual(sm.image_base, sm_export['url'])
                    self.assertEqual(sm.tile_width, sm_export['tile_width'])
                    self.assertEqual(sm.tile_height, sm_export['tile_height'])
                    self.assertEqual(sm.tile_source_type, sm_export['tile_source_type'])
                    self.assertEqual(sm.file_extension, sm_export['fileextension'])

                for sge in s.get('stackgroups', []):
                    sg_id = sge['id']
                    self.assertIn(sg_id, valid_stackgroup_ids)
                    self.assertNotIn(sg_id, seen_stackgroups)
                    seen_stackgroups.append(sg_id)

                    sg = StackGroup.objects.get(id=sg_id)
                    sg_link = StackStackGroup.objects.get(
                        stack=stack, stack_group=sg)
                    self.assertEqual(sg.title, sge['title'])
                    self.assertEqual(sg_link.group_relation.name, sge['relation'])

                # Make sure we have seen all relevant stack groups
                self.assertCountEqual(valid_stackgroup_ids, seen_stackgroups)

            # Make sure we have seen all relevant stacks
            self.assertCountEqual(valid_stack_ids, seen_stacks)

        self.assertCountEqual(valid_project_ids, seen_projects)
Пример #8
0
def get_data_view( request, data_view_id ):
    """ Returns a rendered template for the given view.
    """
    # Load the template
    dv = get_object_or_404(DataView, pk=data_view_id)
    code_type = dv.data_view_type.code_type
    template = loader.get_template( "catmaid/" + code_type + ".html" )
    # Get project information and pass all to the template context
    config = json.loads( dv.config )

    # Get all the projects that are visible for the current user
    projects = get_project_qs_for_user(request.user)

    # If requested, filter projects by tags. Otherwise, get all.
    if "filter_tags" in config:
        filter_tags = config["filter_tags"]
        # Only get projects that have all the filter tags set
        # TODO: Improve performande by not using an IN query (but a temp table
        # join) over all filter_tags.
        projects = projects.filter( tags__name__in=filter_tags ).annotate(
            repeat_count=Count("id") ).filter( repeat_count=len(filter_tags) )

    show_stacks = config.get('show_stacks', True)
    show_stackgroups = config.get('show_stackgroups', True)

    # Make sure we get all needed stacks in the first query
    if show_stacks:
        projects = projects.prefetch_related('stacks')

    # Build a stack index
    stack_index = defaultdict(list)
    stacks_of = defaultdict(list)

    if show_stacks:
        for p in projects:
            for s in p.stacks.all():
                stack_index[s.id] = s
                stacks_of[p.id].append(s)

    # Build a stack group index, if stack groups should be made available
    stackgroup_index = defaultdict(list)
    stackgroups_of = defaultdict(list)
    if show_stackgroups:
        # Get all
        stackgroups = StackGroup.objects.filter(project__in=projects)
        for sg in stackgroups:
            stackgroup_index[sg.id] = sg
            stackgroups_of[sg.project_id].append(sg)

    # Extend the project list with additional information like editabilty
    projects = extend_projects( request.user, projects )

    # Sort by default
    if "sort" not in config or config["sort"] == True:
        projects = natural_sort( projects, "title" )

    # Build project index
    project_index = dict([(p.id, p) for p in projects])
    project_ids = set(project_index.keys())

    # Build tag index
    ct = ContentType.objects.get_for_model(Project)
    tag_links = TaggedItem.objects.filter(content_type=ct) \
        .values_list('object_id', 'tag__name')
    tag_index = defaultdict(set)
    for pid, t in tag_links:
        if pid in project_ids:
            tag_index[t].add(pid)

    context = {
        'data_view': dv,
        'projects': projects,
        'config': config,
        'settings': settings,
        'tag_index': tag_index,
        'project_index': project_index,
        'stack_index': stack_index,
        'stacks_of': stacks_of,
        'stackgroup_index': stackgroup_index,
        'stackgroups_of': stackgroups_of,
        'STATIC_URL': settings.STATIC_URL,
    }

    return HttpResponse( template.render( context ) )
Пример #9
0
def get_data_view(request, data_view_id):
    """ Returns a rendered template for the given view.
    """
    # Load the template
    dv = get_object_or_404(DataView, pk=data_view_id)
    code_type = dv.data_view_type.code_type
    template = loader.get_template("catmaid/" + code_type + ".html")
    # Get project information and pass all to the template context
    config = json.loads(dv.config)

    # Get all the projects that are visible for the current user
    projects = get_project_qs_for_user(request.user).prefetch_related('stacks')

    # If requested, filter projects by tags. Otherwise, get all.
    if "filter_tags" in config:
        filter_tags = config["filter_tags"]
        # Only get projects that have all the filter tags set
        projects = projects.filter(tags__name__in=filter_tags).annotate(
            repeat_count=Count("id")).filter(repeat_count=len(filter_tags))

    # Build a stack index
    stack_index = defaultdict(list)
    stacks_of = defaultdict(list)
    for p in projects:
        for s in p.stacks.all():
            stack_index[s.id] = s
            stacks_of[p.id].append(s)

    # Extend the project list with additional information like editabilty
    projects = extend_projects(request.user, projects)

    # Sort by default
    if "sort" not in config or config["sort"] == True:
        projects = natural_sort(projects, "title")

    # Build project index
    project_index = dict([(p.id, p) for p in projects])
    project_ids = set(project_index.keys())

    # Build tag index
    ct = ContentType.objects.get_for_model(Project)
    tag_links = TaggedItem.objects.filter(content_type=ct) \
        .values_list('object_id', 'tag__name')
    tag_index = defaultdict(set)
    for pid, t in tag_links:
        if pid in project_ids:
            tag_index[t].add(pid)

    context = Context({
        'data_view': dv,
        'projects': projects,
        'config': config,
        'settings': settings,
        'tag_index': tag_index,
        'project_index': project_index,
        'stack_index': stack_index,
        'stacks_of': stacks_of,
        'STATIC_URL': settings.STATIC_URL,
    })

    return HttpResponse(template.render(context))