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))
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))
def CHECK(x, y, z = None): result = get_available_tags(x).values_list('name', flat=True) self.assertEqual(sorted(result), sorted(y), z)
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