Exemple #1
0
 def test_split_tags(self):
     CHECK = lambda x, y, z = "": \
             self.assertEqual(sorted(split_tags(x)), sorted(y), z)
     CHECK("first, second, third", ["first", "second", "third"])
     CHECK("First, seCOND, THIRD", ["First", "seCOND", "THIRD"],
             "should keep cases")
     CHECK("two words", ["two words"], "should support multiple word tags")
     CHECK("two   words", ["two words"], "should remove extra spaces")
     CHECK("one, one two, one two three", ["one", "one two", "one two three"])
     CHECK("a,b,c,b", ["a", "b", "c"], "should remove duplicated")
     CHECK("b,,a,,,,c,,d", ["a", "b", "c", "d"], "should remove empty tags")
     CHECK(["already", "split"], ["already", "split"])
     CHECK(None, [], "should accept None as empty list")
     with self.assertRaises(ValueError): split_tags({"a": 124})
     with self.assertRaises(ValueError): split_tags(12312313)
Exemple #2
0
def view(request):
    q = request.GET.get('q')

    if q is not None:
        q = split_tags(q)

    error = []
    tags = list(get_available_tags(q or []).values_list('name', flat=True))
    if q is not None:
        if not q:
            error.append('Navedite barem jednu oznaku!')
        elif len(tags) != len(q):
            diff = set([x.lower() for x in q]) - set([x.lower() for x in tags])
            error.append(u'Nepostojeć%s: %s!' % (
                u'a oznaka' if len(diff) == 1 else 'e oznake',
                u', '.join(diff),
            ))

    kwargs = dict(
        show_hidden = 'show_hidden' in request.GET,
        quality_min = request.GET.get('quality_min'),
        quality_max = request.GET.get('quality_max'),
        difficulty_min = request.GET.get('difficulty_min'),
        difficulty_max = request.GET.get('difficulty_max'),
    )

    groups_error = False
    if request.user.has_perm('advanced_search'):
        if request.GET.get('q') is not None:
            advanced_form = AdvancedSearchForm(request.GET, user=request.user)
            if advanced_form.is_valid():
                kwargs['groups'] = advanced_form.cleaned_data['groups']
            else:
                groups_error = True
        else:
            advanced_form = AdvancedSearchForm(user=request.user)
    else:
        advanced_form = None

    if not error:
        tasks = search_tasks(tags, user=request.user, **kwargs)
        if hasattr(tasks, 'select_related'):
            tasks = tasks.select_related('author', 'content')
    else:
        tasks = Task.objects.none()


    return render_to_response('search.html', {
        'advanced_form': advanced_form,
        'any': bool(request.GET),
        'errors': '<br>'.join(error),
        'form': SearchForm(request.GET),
        'groups_error': groups_error,
        'search_solved_count': bool(kwargs.get('groups')),
        'tasks': tasks,
        'tags': tags,
        }, context_instance=RequestContext(request))
Exemple #3
0
def tag_list_preview(tags):
    """Given a list or a comma-separated list of tags, just render them
    without any logic."""
    tags = split_tags(tags)

    no_plus = u'<a href="/search/?q={}">{}</a>'
    tags_html = [no_plus.format(tag, tag) for tag in tags]

    return mark_safe(u'<div class="tag-list preview">{}</div>'.format(
            u" ".join(tags_html)))
Exemple #4
0
def search(tags=None, tag_ids=None):
    """
        Find all objects whose tags make superset of given tags.

        If any unknown tag given or none tags given at all, returns None.
        Otherwise, returns SearchCache object.
    """
    if tags:
        tags = split_tags(tags)
        if not tags:
            return None # if no tag given, don't just return all objects

        # what if an unknown tag is in the list?
        tag_ids = list(get_available_tags(tags).values_list('id', flat=True))

        if len(tag_ids) != len(tags):
            return None # unknown tag given
    elif not tag_ids:
        return None
    else:
        tag_ids = split_tag_ids(tag_ids)

    # Sort by id before calling.
    return _search_and_cache(sorted(tag_ids))
Exemple #5
0
def reverse_search(input):
    """
        Find all objects whose tags are a subset of given tags.

        Returns SearchCache object if any (existing) tag given, otherwise None.

        Example:
            reverse_search(['imo', '1997'])
            --> SearchCache pointing to:
                --> Folder with filter tag 'imo'
                --> Folder with filter tag 'imo', '1997'
                (...)

            Examples of non matching objects:
            --> Folder with filter tag 'shortlist', '1997'
            --> Task with tags 'imo', '1997', 'geo'
    """
    input = split_tags(input)
    if not input:
        return None # if no tag given, don't just return all objects

    tags = get_available_tags(input)
    if len(tags) != len(input):
        return None

    tag_ids = [x.id for x in tags]
    key = _reverse_search_key(tag_ids)

    try:
        return SearchCache.objects.get(key=key)
    except SearchCache.DoesNotExist:
        pass

    # Create cache object.
    cache = SearchCache(key=key)
    cache.save()
    cache.tags.set(*tags)  # Do not use set_tags here.

    # Generate SQL query
    cache_content_type = ContentType.objects.get_for_model(SearchCache)
    tag_ids = [x.id for x in tags]
    query = 'SELECT DISTINCT A.object_id, A.content_type_id, A.tag_id FROM tags_taggeditem A' \
            '   INNER JOIN tags_taggeditem B'   \
            '       ON (A.object_id = B.object_id AND A.content_type_id = B.content_type_id)'   \
            '   WHERE B.tag_id IN (%s) AND B.content_type_id != %d' \
        % (','.join([str(id) for id in tag_ids]), cache_content_type.id)

    # Manually fetch.
    cursor = connection.cursor()
    cursor.execute(query)
    tagged_items = cursor.fetchall()

    # Generate and save search result.
    objects = defaultdict(set)
    for object_id, content_type_id, tag_id in tagged_items:
        # Seperate tagged items by objects (get tags for each object)
        objects[(object_id, content_type_id)].add(tag_id)

    ids_set = set(tag_ids)

    # Filter only those objects whose tags are subset of the given set of tags
    SearchCacheElement.objects.bulk_create(
        SearchCacheElement(object_id=key[0], content_type_id=key[1], cache=cache)
        for key, obj_tags in objects.iteritems()
        if obj_tags.issubset(ids_set)
    )

    return cache