Beispiel #1
0
 def test_signal_setup_handling(self):
     old_ui = connections['default'].get_unified_index()
     connections['default']._index = UnifiedIndex()
     self.assertEqual(connections['default'].get_unified_index()._indexes_setup, False)
     foo_1 = Foo.objects.create(
         title='chekin sigalz',
         body='stuff'
     )
     fi = connections['default'].get_unified_index().get_index(Foo)
     fi.clear()
     fi.update()
     
     sqs = SearchQuerySet()
     existing_foo = sqs.filter(id='discovery.foo.1')[0]
     self.assertEqual(existing_foo.text, u'stuff')
     
     fi.clear()
     foo_1 = Foo.objects.get(pk=1)
     foo_1.title = 'Checking signals'
     foo_1.body = 'Stuff.'
     # This save should trigger an update.
     foo_1.save()
     self.assertEqual(connections['default'].get_unified_index()._indexes_setup, True)
     
     sqs = SearchQuerySet()
     new_foo = sqs.filter(id='discovery.foo.1')[0]
     self.assertEqual(new_foo.text, u'Stuff.')
     connections['default']._index = old_ui
Beispiel #2
0
    def search(self):
        # First, store the SearchQuerySet received from other processing.
        sqs = super(CustomSearchForm, self).search()
        # import ipdb; ipdb.set_trace();

        if not self.is_valid():
            return self.no_query_found()

        # Check to see if a start_date was chosen.

        if self.cleaned_data['q']:
            sqs = SearchQuerySet().facet('author')
            sqs_content = sqs.filter(content_auto=self.cleaned_data['q'])
            sqs_title = sqs.filter(title_auto=self.cleaned_data['q'])
            sqs = sqs_content|sqs_title

        if self.cleaned_data['start_date']:
            sqs = sqs.filter(pub_date__gte=self.cleaned_data['start_date'])

        # Check to see if an end_date was chosen.
        if self.cleaned_data['end_date']:
            sqs = sqs.filter(pub_date__lte=self.cleaned_data['end_date'])

        if self.selected_facets:
            faceted_query_set = EmptySearchQuerySet()
            for facet in self.selected_facets:
                if 'author' in facet:
                    author_exact = facet.split(':')
                    author_name = author_exact[len(author_exact)-1]
                    faceted_query_set = SearchQuerySet().filter(author=author_name)|faceted_query_set

            sqs = sqs&faceted_query_set


        return sqs
Beispiel #3
0
 def search_filter(self, filters=None, *args, **kwargs):
     sqs = SearchQuerySet()
     user = kwargs.get('user', None)
     groups = []
     if user and user.is_authenticated():
         groups = [g.pk for g in user.group_set.all()]
     admin = user.profile.is_superuser
     
     # permission filters
     if user:
         if not user.profile.is_superuser:
             if not user.is_anonymous():
                 # (status+status_detail+(anon OR user)) OR (who_can_view__exact)
                 anon_query = Q(allow_anonymous_view=True)
                 user_query = Q(allow_user_view=True)
                 sec1_query = Q(status=True, status_detail='active')
                 user_perm_q = Q(users_can_view__in=[user.pk])
                 group_perm_q = Q(groups_can_view__in=groups)
                 
                 query = reduce(operator.or_, [anon_query, user_query])
                 query = reduce(operator.and_, [sec1_query, query])
                 query = reduce(operator.or_, [query, user_perm_q, group_perm_q])
             else:
                 sqs = sqs.filter(allow_anonymous_view=True)
     else:
         sqs = sqs.filter(allow_anonymous_view=True)
     
     # custom filters
     for filter in filters:
         sqs = sqs.filter(content='"%s"' % filter)
     
     return sqs.models(self.model)
Beispiel #4
0
def search(request):
    request.session['prev_url'] = request.build_absolute_uri()
    q = request.GET.get('q')
    levels = request.GET.get('levels')
    counties = request.GET.get('counties')
    categories = request.GET.get('categories')

    # Text query
    if q is None:
        results = SearchQuerySet().all()
    else:
        results = SearchQuerySet().filter(content=AutoQuery(q))

    # Add filters
    results = results.filter(state=request.state_filter)
    if levels:
        levels = levels.split('-')
        results = results.filter(level__in=levels)
    if categories:
        categories = categories.split('-')
        results = results.filter(category__in=categories)
    if counties:
        counties = counties.split('-')
        results = results.filter(county__in=counties)

    rtitle = "Showing %s results" % len(results)
    levels = ['state', 'county', 'municipal']
    return render(request, 'bids/search.html',
        {'result_title': rtitle, 'results': results, 'cats': BidCategory.choices(),
         'counties': County.choices(), 'levels': levels })
Beispiel #5
0
  def get_queryset(self):
    params = self.request.GET

    highlighted = params.get('highlighted') == 'true'
    if highlighted:
      return Project.objects.filter(highlighted=highlighted)

    query = params.get('query', None)
    cause = params.get('cause', None)
    skill = params.get('skill', None)
    city = params.get('city', None)
    nonprofit = params.get('nonprofit', None)

    if nonprofit:
      nonprofit = Nonprofit.objects.get(user__slug=nonprofit)
      queryset = Project.objects.filter(nonprofit=nonprofit)
    else:
        queryset = SearchQuerySet().models(Project)
    queryset = queryset.filter(causes=cause) if cause else queryset
    queryset = queryset.filter(skills=skill) if skill else queryset
    queryset = queryset.filter(city=city) if city else queryset
    queryset = queryset.filter(content=query).boost(query, 2) if query else queryset
    results = [ r.pk for r in queryset]

    return Project.objects.filter(pk__in=results, deleted=False, closed=False, published=True).order_by('?')
Beispiel #6
0
    def search(self, query=None, *args, **kwargs):
        """
        haystack to query corporate memberships.
        Returns a SearchQuerySet
        """
        from corporate_memberships.models import CorporateMembership
        from perms.utils import is_admin

        user = kwargs.get('user', None)
        if user.is_anonymous():
            return SearchQuerySet().models().none()

        is_an_admin = is_admin(user)

        sqs = SearchQuerySet().models(CorporateMembership)

        if query:
            sqs = sqs.filter(content=sqs.query.clean(query))
        else:
            sqs = sqs.all()

        if not is_an_admin:
            # reps__contain
            sqs = sqs.filter(Q(content='rep\:%s' % user.username) |
                             Q(creator=user) |
                             Q(owner=user)).filter(status_detail='active')

        return sqs
    def __init__(self, *args, user, report_ids=(), **kwargs):
        sqs = SearchQuerySet().models(Report)

        # Ensure anonymous/public users cannot see non-public reports in all
        # cases.
        if not user.is_active:
            if report_ids:
                sqs = sqs.filter(SQ(id__in=report_ids) | SQ(is_public=True))
            else:
                sqs = sqs.filter(is_public=True)

        super().__init__(*args, searchqueryset=sqs, **kwargs)

        self.user = user
        self.report_ids = report_ids

        # Only certain fields on this form can be used by members of the
        # public.
        if not user.is_active:
            for name in self.fields.keys():
                if name not in self.public_fields:
                    self.fields.pop(name)

        if user.is_anonymous():
            if report_ids:
                source_field = self.fields['source']
                source_choices = source_field.choices
                source_field.choices = [
                    (value, label) for (value, label) in source_choices if value != 'invited']
            else:
                self.fields.pop('source')
    def search(self):
        sqs = SearchQuerySet().load_all()

        if not self.is_valid():
            return sqs

        if self.cleaned_data['q']:
            #search input of a code, contains at least '_YYYY_'
            if not re.match('([a-zA-Z]*_?[EI])?_[0-9]{4}_([0-9]{3}_[0-9]{3})?', self.cleaned_data.get('q')):
                sqs = sqs.filter(content__contains=self.cleaned_data['q']).facet('item_acces').facet('item_status').facet('digitized').facet('recording_context').facet('physical_format').facet('media_type')
            else:
                sqs = sqs.filter(code__exact=self.cleaned_data['q']).facet('item_acces').facet('item_status').facet('digitized').facet('recording_context').facet('physical_format').facet('media_type')
                print(self.cleaned_data['q'])

        for facet in self.selected_facets:
            if ":" not in facet:
                continue

            field, value = facet.split(":", 1)

            if value:
                if value == 'viewable':
                    sqs = sqs.narrow('item_acces:full OR item_acces:mixed').narrow('digitized:T')
                else:
                    sqs = sqs.narrow(u'%s:"%s"' % (field, sqs.query.clean(value)))

        return sqs
def search(request, template_name="django_messages/search.html"):
    search_term = request.GET.get("qs")
    search_filter = request.GET.get("search")

    results = SearchQuerySet().filter(participants=request.user.pk).filter(
        SQ(content__icontains=search_term) | SQ(participant_last_names__istartswith=search_term)
    ).order_by('-last_message')

    if request.GET.get('search')==u'sent':
        results = results.filter(participant_sent=u"{}-{}".format(request.user.pk, True))
    elif request.GET.get('search')==u'inbox':
        results = results.filter(participant_archived=u"{}-{}".format(request.user.pk, False))
    elif request.GET.get('search')==u'archives':
        results = results.filter(participant_archived=u"{}-{}".format(request.user.pk, True))
    else:
        pass

    results = results
    paginated_messages = Paginator(results, 10)
    page = request.GET.get('page', 1)

    try:
        paginated_list = paginated_messages.page(page)
    except EmptyPage:
        paginated_list = paginated_messages.page(paginated_messages.num_pages)
    except PageNotAnInteger:
        paginated_list = paginated_messages.page(1)

    return render_to_response(template_name, {
        "thread_results": paginated_list,
        "search_term": search_term,
        "search_filter": search_filter,
        'page_type': 'search',
        }, context_instance=RequestContext(request))
Beispiel #10
0
    def search(self):
        if not hasattr(self, 'cleaned_data'):
            return self.no_query_found()
        elif not self.cleaned_data['q']:
            sqs = SearchQuerySet()
        else:
            sqs = super(ToolForm, self).search()

        bool_fields = [
            'supports_osx', 'supports_windows', 'supports_linux', 'supports_web_based',
            'capture', 'capture_os', 'capture_code', 'capture_workflow', 'capture_data',
            'representation', 'representation_descriptive_only', 'representation_executable',
            'replicability',
            'modifiability',
#            'portability',
            'longevity', 'longevity_archiving', 'longevity_upgrading',
            'document_linkage', 'document_linkage_by_reference', 'document_linkage_inline',
            'experiment_sharing', 'experiment_sharing_archival', 'experiment_sharing_hosted_execution'
            ]
        for field in bool_fields:
            if field in self.cleaned_data and self.cleaned_data[field]:
                sqs = sqs.filter(**{field:self.cleaned_data[field]=='True'})

        if 'portability' in self.cleaned_data and self.cleaned_data['portability']:
            sqs = sqs.filter(portability=self.cleaned_data['portability'])
        return sqs
    def get_section_data(self, section):
        defaults = self.search_sections[section]
        extra_filter = defaults.get('filter', {})
        filter_args = extra_filter.get('args', [])
        filter_kwargs = extra_filter.get('kwargs', {})
        extra_exclude = defaults.get('exclude', {})
        query = SearchQuerySet().models(defaults['model'])
        if extra_exclude:
            query = query.exclude(**extra_exclude)
        query = query.filter(
            content=AutoQuery(self.query),
            *filter_args,
            **filter_kwargs
        )

        if self.start_date_range:
            query = query.filter(start_date__gte=self.start_date_range)

        if self.end_date_range:
            query = query.filter(start_date__lte=self.end_date_range)

        if self.order == 'date':
            query = query.order_by('-start_date')

        result = defaults.copy()
        result['results'] = query.highlight()
        result['results_count'] = result['results'].count()
        result['section'] = section
        result['section_dashes'] = section.replace('_', '-')
        return result
Beispiel #12
0
 def get(self, request, *args, **kwargs):
     term = request.GET.get('term', '').strip()
     if len(term) > 0:
         sqs = SearchQuerySet().using(settings.FIAS_HAYSTACK_CONNECTION_ALIAS).models(AddrObj)
         aolevels = request.GET.get('aolevels', '')
         aolevels = list(map(int, filter(lambda s: s not in EMPTY_VALUES, map(strip, aolevels.split(',')))))
         if aolevels:
             sqs = sqs.filter(aolevel__in=aolevels)
         socrs = request.GET.get('socrs', '')
         socrs = list(filter(lambda s: s not in EMPTY_VALUES, map(strip, socrs.split(','))))
         if socrs:
             sqs = sqs.filter(shortname__in=socrs)
         cleaned_words = [sqs.query.clean(word.strip()) for word in term.split(' ')]
         query_bits = [SQ(text_auto=word) for word in cleaned_words if word]
         if query_bits:
             sqs = sqs.filter(six.moves.reduce(operator.__or__, query_bits))
         items = sqs
         items = items[:50]
     else:
         items = []
     return JsonResponse({
         'results': [
             {'id': l.aoguid, 'text': l.full_name, 'level': l.aolevel} for l in items
         ],
         'more': False
     })
Beispiel #13
0
def cruce10(form):
    #Revizar que este en el estado seleccionado
    if form.cleaned_data['codigo'] != '':
        sqs = SearchQuerySet()
        sqs = sqs.filter(estado = form.cleaned_data['estado']).filter(codigo = form.cleaned_data['codigo'])
        if sqs != []:
            for yac in sqs:
                if len(yac.manifestacion) != 0:
                    if yac.manifestacion[0].encode('utf8') != 'None':
                        if int(yac.manifestacion[0]) <= 22:
                            yac.manifestacion = MANIFESTACIONES[int(yac.manifestacion[0])]
            return {
            'yacimientos': sqs}

        else:
            return {
            'yacimientos': sqs}

    #Buscar en todo ese estado
    elif form.cleaned_data['codigo'] == '':
        sqs = SearchQuerySet()
        sqs = sqs.filter(estado = form.cleaned_data['estado'])
        for yac in sqs:
            if len(yac.manifestacion) != 0:
                if yac.manifestacion[0].encode('utf8') != 'None':
                    if int(yac.manifestacion[0]) <= 22:
                        yac.manifestacion = MANIFESTACIONES[int(yac.manifestacion[0])]

        return {
        'yacimientos': sqs}
Beispiel #14
0
    def build_form(self, form_kwargs=None):
        log = logging.getLogger(".".join((__name__, "PostSearch")))
        request = self.request

        log.debug("which author has domain %r?", request.META["HTTP_HOST"])
        try:
            self.author = User.objects.get(authorsite__site__domain=request.META["HTTP_HOST"])
        except User.DoesNotExist:
            log.debug("    no such author! no results at all!")
            self.author = None
            sqs = SearchQuerySet().none()
        else:
            sqs = SearchQuerySet().filter(author_pk=self.author.pk)
            # What visibility of posts can the searcher see?
            if request.user.is_anonymous():
                log.debug("    viewer is anonymous, so only %s's public posts", self.author.username)
                sqs = sqs.filter(private=0)
            elif request.user.pk == self.author.pk:
                log.debug("    viewer is %s, so all their posts", self.author.username)
            else:
                # TODO: honor trust groups instead of giving everyone else only public posts
                log.debug("    viewer is logged in as somebody else, so only %s's public posts", self.author.username)
                sqs = sqs.filter(private=0)

        self.searchqueryset = sqs

        return super(PostSearch, self).build_form(form_kwargs)
Beispiel #15
0
    def get_global_context(self, context):
        # Find all the models to search over...
        models = set(self.search_sections[section]["model"] for section in self.search_sections)

        show_top_hits = self.page == "1" or not self.page

        top_hits_ids = []

        if show_top_hits:
            context["top_hits"] = []
            for section, max_for_top_hits in SearchBaseView.top_hits_under.items():
                data = self.get_section_data(section)
                if data["results_count"] <= max_for_top_hits:
                    context["top_hits"] += data["results"]
            top_hits_ids = set(r.id for r in context["top_hits"])

        sqs = SearchQuerySet().models(*list(models))
        # Exclude anything that will already have been shown in the top hits:
        for top_hit_id in top_hits_ids:
            sqs = sqs.exclude(id=top_hit_id)
        sqs = sqs.exclude(hidden=True).filter(content=AutoQuery(self.query)).highlight()

        if self.start_date_range:
            sqs = sqs.filter(start_date__gte=self.start_date_range)

        if self.end_date_range:
            sqs = sqs.filter(start_date__lte=self.end_date_range)

        if self.order == "date":
            sqs = sqs.order_by("-start_date")

        context["paginator"] = Paginator(sqs, self.results_per_page)
        context["page_obj"] = self.get_paginated_results(context["paginator"])
        return context
Beispiel #16
0
    def get_results(self, name, branch, year, offset, branch_facet, year_facet, city_facet):
        if year_facet:
            year_facet = [int(x) for x in year_facet.split(",")]

        sqs = SearchQuerySet().facet('branch')
        sqs = sqs.facet('year_of_passing')
        sqs = sqs.facet('city')

        if name:
            sqs = sqs.auto_query(name)
        if branch:
            sqs = sqs.filter(branch_exact=branch)
        if year:
            sqs = sqs.filter(year_of_passing_exact=year)
        if branch_facet:
            sqs = sqs.filter(branch_exact=branch_facet)
        if year_facet:
            sqs = sqs.filter(year_of_passing_exact__in=year_facet)
        if city_facet:
            sqs = sqs.filter(city_exact=city_facet)

        offsetvalue = int(offset)
        results = sqs.order_by('name')[offsetvalue:offsetvalue + INITIAL_RESULTS_COUNT]
        resultcount = len(results)

        return results, resultcount
Beispiel #17
0
    def get_queryset(self):
        params = self.request.GET

        highlighted = params.get("highlighted") == "true"
        if highlighted:
            return Project.objects.filter(highlighted=highlighted)

        query = params.get("query", None)
        cause = params.get("cause", None)
        skill = params.get("skill", None)
        city = params.get("city", None)
        nonprofit = params.get("nonprofit", None)

        if nonprofit:
            nonprofit = Nonprofit.objects.get(user__slug=nonprofit)
            queryset = Project.objects.filter(nonprofit=nonprofit)
        else:
            queryset = SearchQuerySet().models(Project)
        queryset = queryset.filter(causes=cause) if cause else queryset
        queryset = queryset.filter(skills=skill) if skill else queryset
        queryset = queryset.filter(content=query) if query else queryset
        queryset = queryset.filter(city=city) if city != u"" and int(city) else queryset

        results = [q.pk for q in queryset]

        if city == "0":
            return Project.objects.filter(
                pk__in=results, deleted=False, closed=False, published=True, work__can_be_done_remotely=True
            ).order_by("-highlighted")
        else:
            return Project.objects.filter(pk__in=results, deleted=False, closed=False, published=True).order_by(
                "-highlighted"
            )
Beispiel #18
0
    def get_section_data(self, section):
        defaults = self.search_sections[section]
        extra_filter = defaults.get("filter", {})
        filter_args = extra_filter.get("args", [])
        filter_kwargs = extra_filter.get("kwargs", {})
        extra_exclude = defaults.get("exclude", {})
        query = SearchQuerySet().models(defaults["model"])
        if extra_exclude:
            query = query.exclude(**extra_exclude)
        query = query.filter(content=AutoQuery(self.query), *filter_args, **filter_kwargs)

        if self.start_date_range:
            query = query.filter(start_date__gte=self.start_date_range)

        if self.end_date_range:
            query = query.filter(start_date__lte=self.end_date_range)

        if self.order == "date":
            query = query.order_by("-start_date")

        result = defaults.copy()
        result["results"] = query.highlight()
        result["results_count"] = result["results"].count()
        result["section"] = section
        result["section_dashes"] = section.replace("_", "-")
        return result
Beispiel #19
0
def volunteer_page(request):
    # Get the user comfort languages list 
    user_langs = get_user_languages_from_request(request)

    relevant = SearchQuerySet().result_class(VideoSearchResult) \
        .models(Video).filter(video_language_exact__in=user_langs) \
        .filter_or(languages_exact__in=user_langs) \
        .order_by('-requests_count')

    featured_videos =  relevant.filter(
        featured__gt=datetime.datetime(datetime.MINYEAR, 1, 1)) \
        .order_by('-featured')[:5]

    popular_videos = relevant.order_by('-week_views')[:5]

    latest_videos = relevant.order_by('-edited')[:15]

    requested_videos = relevant.filter(requests_exact__in=user_langs)[:5]

    context = {
        'featured_videos': featured_videos,
        'popular_videos': popular_videos,
        'latest_videos': latest_videos,
        'requested_videos': requested_videos,
        'user_langs':user_langs,
    }

    return render_to_response('videos/volunteer.html', context,
                              context_instance=RequestContext(request))
Beispiel #20
0
def get_user_events_sqs(user):
    events = SearchQuerySet().models(Event)
    if is_student(user):
        return events.filter(SQ(is_public=True) | SQ(invitees=user.id))
    if is_campus_org(user):
        return events.filter(owner=user.id)
    return events.filter(SQ(owner=user.id) | SQ(attending_employers=user.recruiter.employer.id))
Beispiel #21
0
def _specific_view(user, obj):
    """
    determines if a user has specific permissions to view the object.
    note this is based only on:

    (users_can_view contains user)
    +
    (groups_can_view contains one of user's groups)
    """
    sqs = SearchQuerySet()
    sqs = sqs.models(obj.__class__)

    groups = [g.pk for g in user.group_set.all()]

    q_primary_key = SQ(primary_key=obj.pk)
    q_groups = SQ(groups_can_view__in=groups)
    q_users = SQ(users_can_view__in=[user.pk])

    if groups:
        sqs = sqs.filter(q_primary_key & (q_groups | q_users))
    else:
        sqs = sqs.filter(q_primary_key & q_users)

    if sqs:
        # Make sure the index isn't doing something unexpected with the query,
        # like when the Whoosh StopFilter caused the primary_key portion of the
        # query to be ignored.
        assert len(sqs) == 1, "Index returned an unexpected result set when searching for view permissions on an object"
        return True

    return False
Beispiel #22
0
class AutocompleteQueryTestCase(TestCase):

    fixtures = ['mock_persons']

    def setUp(self):
        PersonIndex().reindex()
        self.sqs = SearchQuerySet().all()

    def test_filter_CharField(self):
        # Make sure we only get exact hit when searching using
        # the `CharField` fields
        self.assertEqual(self.sqs.filter(firstname='abel').count(),
                         Person.objects.filter(firstname__iexact='abel').count())

        self.assertEqual(self.sqs.filter(lastname='hood').count(),
                         Person.objects.filter(lastname__iexact='hood').count())

    def test_filter_AutocompleteEdgeNgramField(self):
        # Make sure we get results for all tokens indexed using
        # the `AutocompleteEdgeNgramField`. We should get match on
        # both firstname and lastname.
        self.assertEqual(self.sqs.autocomplete(q='d').count(),
                         Person.objects.filter(Q(firstname__istartswith='d') |
                                               Q(lastname__istartswith='d')).count())

        self.assertEqual(self.sqs.autocomplete(q='ab').count(),
                         Person.objects.filter(Q(firstname__istartswith='ab') |
                                               Q(lastname__istartswith='ab')).count())
def search(request):
    """Use haystack to find search results"""
    term = request.GET.get('q', '')
    version = request.GET.get('version', '')
    regulation = request.GET.get('regulation', '')
    try:
        page = int(request.GET.get('page', '0'))
    except ValueError:
        page = 0

    if not term:
        return user_error('No query term')

    query = SearchQuerySet().models(Regulation).filter(content=term)
    if version:
        query = query.filter(version=version)
    if regulation:
        query = query.filter(regulation=regulation)

    start, end = page * PAGE_SIZE, (page+1) * PAGE_SIZE

    return success({
        'total_hits': len(query),
        'results': transform_results(query[start:end])
    })
Beispiel #24
0
def cruce19(form):
    filters = ['litica',
    'ceramica',
    'oseo',
    'concha',
    'carbon no superficial',
    'mitos',
    'cementerios',
    'monticulos',
    'otros'
    ]
    list = 0
    try:
        list = filters.index(form.cleaned_data['manifasociadas'].lower()) + 1
        sqs = SearchQuerySet()
        sqs = sqs.filter(pais = 'Venezuela').filter(manifasociadas = list)
        yacimientos = {}
        lista = []
        for estado in ESTADOS:
            lista = sqs.filter(estado = estado)
            yacimientos[estado] = lista
        return {
        'manifa':form.cleaned_data['manifasociadas'],
        'yacimientos': yacimientos}

    except:
        return {}
Beispiel #25
0
    def get_content(self):
        qs = SearchQuerySet()
        search_fields = {
            'q': 'text',
            'controlling_bodies': 'controlling_body',
            'statuses': 'status',
            'file_types': 'file_type',
        }

        for key, val in self.filter.iteritems():
            if key in search_fields:
                field = search_fields[key]
            else:
                field = key

            if val in ([], {}, '', (), None):
                continue

            if isinstance(val, list):
                for item in val:
                    qs = qs.filter(**{field: item})
            else:
                qs = qs.filter(**{field: val})

        return qs.order_by('order_date')
Beispiel #26
0
    def search(self):
        sqs = SearchQuerySet()
        sqs = sqs.facet('bureaux').facet(
            'section').facet('annee').facet('partenaire')

        if self.q:
            sqs = sqs.filter(content=sqs.query.clean(self.q))

        if self.courant:
            sqs = sqs.filter(date_fin__gte=datetime.date.today())
        if self.cloture:
            sqs = sqs.filter(date_fin__lt=datetime.date.today())

        self.selected_facets = list(
            set(self.selected_facets.split('&') + self.selected_facets_get))

        for facet in self.selected_facets:
            if "__" not in facet:
                continue

            field, value = facet.split("__", 1)

            if value:
                sqs = sqs.narrow(u'%s:"%s"' % (field, sqs.query.clean(value)))

        return sqs
Beispiel #27
0
def _specific_view(user, obj):
    """
    determines if a user has specific permissions to view the object.
    note this is based only on:

    (users_can_view contains user)
    +
    (groups_can_view contains one of user's groups)
    """
    sqs = SearchQuerySet()
    sqs = sqs.models(obj.__class__)

    groups = [g.pk for g in user.group_set.all()]

    q_primary_key = SQ(primary_key=obj.pk)
    q_groups = SQ(groups_can_view__in=groups)
    q_users = SQ(users_can_view__in=[user.pk])

    if groups:
        sqs = sqs.filter(q_primary_key & (q_groups | q_users))
    else:
        sqs = sqs.filter(q_primary_key & q_users)

    if sqs:
        return True

    return False
Beispiel #28
0
    def get_queryset(self):
        if self.request.method in SAFE_METHODS:
            # Listing/searching.

            validate_request_on_app_id(self.request)
            if "q" in self.request.query_params:
                search_q = self.request.query_params["q"]
            else:
                # No query is provided. Full list is for authenticated requests only.
                if not self.request.user.is_authenticated():
                    raise NotAuthenticated("")
                return Picture.objects.order_by("item_id")

            search_q = search_q.strip()
            search_q = search_q.lower()
            search_q = re.sub(r"\s+", " ", search_q)

            search_q = search_q.replace("-", " ")
            search_q = search_q.replace(".", "")
            search_q = search_q.replace("'", "")
            search_q = search_q.strip()

            if not search_q:
                return Picture.objects.none()

            sqs = SearchQuerySet().models(Picture)
            sqs = sqs.filter(content=AutoQuery(search_q))

            pictures = [sr.object for sr in sqs.load_all()]

            if not pictures:
                # Auto-correction.
                sugg = sqs.spelling_suggestion()
                if (sugg is not None) and ("suggestion" in sugg) and sugg["suggestion"]:
                    sqs = SearchQuerySet().models(Picture)
                    sqs = sqs.filter(content=sugg["suggestion"][0])
                    pictures = [sr.object for sr in sqs.load_all()]

            # Exclude hidden.
            pictures = [picture for picture in pictures if not picture.is_hidden]

            # Randomize leading good ones.
            first_non_good_picture_pos = None
            for i, picture in enumerate(pictures):
                if not picture.is_good:
                    first_non_good_picture_pos = i
                    break
            if first_non_good_picture_pos is not None:
                leading_good_pictures = pictures[:first_non_good_picture_pos]
                random.shuffle(leading_good_pictures)
                pictures = leading_good_pictures + pictures[first_non_good_picture_pos:]

            if BOOST_SEARCH_RESULTS_ON_NUM_USES:
                pictures = boost_search_results_on_num_uses(pictures)

            return pictures

        else:
            return Picture.objects.all()
Beispiel #29
0
 def get_context_data(self, **kwargs):
     sqs = SearchQuerySet().models(Boot).order_by('-star_count_month')
     kwargs['trending'] = {
         'projects': sqs.filter(type_exact=Boot.TYPE_PROJECT),
         'apps': sqs.filter(type_exact=Boot.TYPE_APP),
         'cookiecutters': sqs.filter(type_exact=Boot.TYPE_COOKIECUTTER),
     }
     return super(IndexView, self).get_context_data(**kwargs)
Beispiel #30
0
    def get_queryset(self, query_args):
        # Create new queryset
        qs = SearchQuerySet()

        # Are we searching all models or just a specific one (depends on
        # parameter set in View instantiation)
        if self.search_model is not None:
            qs = qs.models(self.search_model)

        # Do we have a query or are we just getting all of them?
        if 'q' in query_args:
            qry = query_args['q']
            # fuzzify search
            qry = u'{}~'.format(qry.replace(' ', '~ '))
            qs = qs.auto_query(qry)
        elif 'parl_id' in query_args:
            qs = qs.filter(parl_id=query_args['parl_id'])
            if 'llp_numeric' in query_args:
                qs = qs.filter(llps_numeric=query_args['llp_numeric'])
            return (qs.all(), None)

        # Filter by facets
        if query_args['facet_filters']:
            for facet_field in query_args['facet_filters'].keys():
                # We use narrow to limit the index entries beforehand, but
                # need to use filter afterwards to remove partly correct results
                # For instance, searching for Steyr (Oberoesterreich) yielded
                # everyone from Oberoesterreich until filtering by it again.
                qs = qs.narrow(u"{}:{}".format(
                    facet_field,
                    qs.query.clean(query_args['facet_filters'][facet_field]))
                ).filter(
                    **{
                        facet_field: query_args['facet_filters'][facet_field]}
                )

        # Retrieve facets and facet_counts
        facet_counts = []
        if self.facet_fields:
            facets = qs
            for facet_field in self.facet_fields:
                if self.facet_fields[facet_field]['type'] == 'date':
                    facets = facets.date_facet(
                        facet_field,
                        start_date=datetime.date(1900, 1, 1),
                        end_date=datetime.date(2050, 1, 1),
                        gap_by='month')
                if self.facet_fields[facet_field]['type'] == 'field':
                    facets = facets.facet(facet_field)
            facet_counts = facets.facet_counts()

        # Get results and return them
        if 'only_facets' in query_args:
            result = {}
        else:
            result = qs.all()

        return (result, facet_counts)
Beispiel #31
0
def search(request):
    result = {}
    q = request.GET.get('q', '')
    q = ' '.join(group_words(q))
    page = request.GET.get('page', '')
    size = request.GET.get('size', '')
    code = request.GET.get('code', '')
    dept_required = request.GET.get('dept_required', '')
    sortby_param = request.GET.get('sort', '')
    reverse_param = request.GET.get('reverse', '')
    ys = request.GET.get('ys', SEMESTER)

    page_size = size or 10
    sortby = sortby_param or 'time_token'
    reverse = True if reverse_param == 'true' else False
    rev_sortby = '-' + sortby if reverse else sortby

    courses = SearchQuerySet().filter()

    if dept_required:
        try:
            courses = Department.objects.get(
                ys=ys, dept_name=dept_required).required_course.all()
        except:
            pass
        if courses:
            result['type'] = 'required'
            page_size = courses.count()
    else:
        courses = courses.filter(content=AutoQuery(q))
        if code:
            courses = courses.filter(code__contains=code)

        if code in ['GE', 'GEC']:
            core = request.GET.get(code.lower(), '')
            if core:
                courses = courses.filter(ge__contains=core)
    courses = courses.order_by(rev_sortby)
    paginator = Paginator(courses, page_size)

    try:
        courses_page = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        courses_page = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        courses_page = paginator.page(paginator.num_pages)

    course_list = [
        {k: v
         for (k, v) in x.__dict__.items() if not k.startswith('_')} for x in
        [x if dept_required else x.object for x in courses_page.object_list]
    ]

    result['total'] = courses.count()
    result['page'] = courses_page.number
    result['courses'] = course_list
    result['page_size'] = page_size

    return JsonResponse(result)
Beispiel #32
0
def search(request, template='search/search.html', load_all=True,
           form_class=ModelSearchForm, searchqueryset=None,
           context_class=RequestContext, extra_context=None, results_per_page=None):
    """
    A more traditional view that also demonstrate an alternative
    way to use Haystack.

    Useful as an example of for basing heavily custom views off of.

    Also has the benefit of thread-safety, which the ``SearchView`` class may
    not be.

    Template:: ``search/search.html``
    Context::
        * form
          An instance of the ``form_class``. (default: ``ModelSearchForm``)
        * page
          The current page of search results.
        * paginator
          A paginator instance for the results.
        * query
          The query received by the form.
    """
    query = ''
    data_domain_ids = []
    results = SearchQuerySet()

    geo_record, indicator = None, None
    try:
        geo_record = GeoRecord.objects.get(
            id=request.GET.get('gid', None))
    except (GeoRecord.DoesNotExist, ValueError):
        # the navigation template tag would pick DEFAULT_GEO_RECORD_ID if no
        # georecord is passed, but we should select it manually here so
        # thumbnails can be rendered in the proper context
        geo_record = GeoRecord.objects.get(id=settings.DEFAULT_GEO_RECORD_ID)

    indicator_results = None
    data_display_results = None

    def _value_to_display(indicator_result):
        datapoint = indicator_result.object.datapoint_set.filter(record=geo_record).order_by('-time__sort')
        value = None
        if datapoint:
            value = datapoint[0].value_set.all()
            if value:
                value = value[0]
        return (indicator_result, value)

    if request.GET.get('q') and request.GET.get('q') != None:
        data_domain_ids = map(lambda id: int(id), request.GET.getlist('data_domain'))
        query = request.GET.get('q')
        results = results.filter(content=query)
        indicator_results = results.filter(records=geo_record.id).models(Indicator)
        data_display_results = results.filter(record_id=geo_record.id).models(DataDisplay)

        if data_domain_ids:
            indicator_results = indicator_results.filter(domains__in=data_domain_ids)
            data_display_results = data_display_results.filter(domains__in=data_domain_ids)

        context = {
            'indicator_results': map(_value_to_display, indicator_results),
            'data_display_results': data_display_results,
            'total_results': data_display_results.count() + indicator_results.count(),
            'query': query,
            'geo_record': geo_record,
            'indicator': indicator,
            'data_domains': DataDomain.objects.all(),
            'data_domain_ids': data_domain_ids,
            'beta':settings.BETA
        }
    else:
        context = {}
    return render_to_response(template, context, context_instance=context_class(request))
Beispiel #33
0
    def get_context_data(self, **kwargs):
        context = super(SearchView, self).get_context_data(**kwargs)
        context['request'] = self.request

        name = self.request.GET.get("name", '')
        branch = self.request.GET.get("branch", '')
        year = self.request.GET.get("year_of_passing", '')

        branch_facet = self.request.GET.get("branch_facet", '')
        year_facet = self.request.GET.get("year_of_passing_facet", '')

        #        results = self.get_results(name, branch, year, offset, branch_facet, year_facet)
        if year_facet:
            year_facet = [int(x) for x in year_facet.split(",")]
        city_facet = self.request.GET.get("city_facet", "")

        sqs = SearchQuerySet().facet('branch')
        sqs = sqs.facet('year_of_passing')
        sqs = sqs.facet('city')

        if name or branch or year:
            context['form'] = ProfileSearchBasicForm(self.request.GET)
            if name:
                sqs = sqs.auto_query(name)
                context['name_selected'] = name
            if branch:
                sqs = sqs.filter(branch_exact=branch)
                context['branch_selected'] = branch
            if year:
                sqs = sqs.filter(year_of_passing_exact=year)
                context['year_selected'] = year
        else:
            context['form'] = ProfileSearchBasicForm()

        context['facets'] = sqs.facet_counts()

        # Horrible hardcoding - need to tweak it - By Srihari
        # To compute the facet counts
        if branch_facet:
            temp = sqs.filter(branch_exact=branch_facet)
            context['facets']['fields']['year_of_passing'] = temp.filter(
                city_exact=city_facet).facet_counts()['fields'][
                    'year_of_passing'] if city_facet else temp.facet_counts(
                    )['fields']['year_of_passing']
        elif city_facet:
            context['facets']['fields']['year_of_passing'] = sqs.filter(
                city_exact=city_facet).facet_counts(
                )['fields']['year_of_passing']

        if year_facet:
            temp = sqs.filter(year_of_passing_exact__in=year_facet)
            context['facets']['fields']['branch'] = temp.filter(
                city_exact=city_facet).facet_counts(
                )['fields']['branch'] if city_facet else temp.facet_counts(
                )['fields']['branch']
        elif city_facet:
            context['facets']['fields']['branch'] = sqs.filter(
                city_exact=city_facet).facet_counts()['fields']['branch']

        if year_facet:
            temp = sqs.filter(year_of_passing_exact__in=year_facet)
            context['facets']['fields']['city'] = temp.filter(
                branch_exact=branch_facet).facet_counts(
                )['fields']['city'] if branch_facet else temp.facet_counts(
                )['fields']['city']
        elif branch_facet:
            context['facets']['fields']['city'] = sqs.filter(
                branch_exact=branch_facet).facet_counts()['fields']['city']

        if branch_facet:
            sqs = sqs.filter(branch_exact=branch_facet)
            context['branch_facet_selected'] = branch_facet
        else:
            context['branch_facet_selected'] = ''

        if year_facet:
            sqs = sqs.filter(year_of_passing_exact__in=year_facet)
            year_facet_string = None
            for year in year_facet:
                if not year_facet_string:
                    year_facet_string = str(year)
                else:
                    year_facet_string = year_facet_string + "," + str(year)
            context['year_facets_selected'] = year_facet_string
        else:
            context['year_facets_selected'] = ''

        if city_facet:
            sqs = sqs.filter(city_exact=city_facet)
            context['city_facet_selected'] = city_facet
        else:
            context['city_facet_selected'] = ''

        context['facets']['fields']['year_of_passing'] = self.facet_sorting(
            context['facets']['fields']['year_of_passing'])
        context['facets']['fields']['city'] = self.facet_sorting(
            context['facets']['fields']['city'])
        context['facets']['fields']['branch'] = self.facet_sorting(
            context['facets']['fields']['branch'])

        results = sqs.order_by('name')[0:INITIAL_RESULTS_COUNT]
        resultcount = sqs.count()
        context['resultcount'] = resultcount
        context['initialoffset'] = INITIAL_RESULTS_COUNT
        context['results'] = results

        return context
Beispiel #34
0
    def search(self, query=None, *args, **kwargs):
        """
            Uses haystack to query groups.
            Returns a SearchQuerySet
        """
        sqs = SearchQuerySet()
        user = kwargs.get('user', None)

        # check to see if there is impersonation
        if hasattr(user, 'impersonated_user'):
            if isinstance(user.impersonated_user, User):
                user = user.impersonated_user

        is_a_superuser = user.profile.is_superuser

        if query:
            sqs = sqs.auto_query(sqs.query.clean(query))
            if user:
                if not is_a_superuser:
                    if not user.is_anonymous:
                        # if b/w superuser and anon

                        # (status+status_detail+(anon OR user)) OR (who_can_view__exact)
                        anon_query = Q(**{
                            'allow_anonymous_view': True,
                        })
                        user_query = Q(**{
                            'allow_user_view': True,
                        })
                        sec1_query = Q(
                            **{
                                'show_as_option': 1,
                                'status': 1,
                                'status_detail': 'active',
                            })
                        sec2_query = Q(
                            **{'who_can_view__exact': user.username})
                        query = reduce(operator.or_, [anon_query, user_query])
                        query = reduce(operator.and_, [sec1_query, query])
                        query = reduce(operator.or_, [query, sec2_query])

                        sqs = sqs.filter(query)
                    else:  # anonymous
                        query = Q(
                            **{
                                'allow_anonymous_view': True,
                                'show_as_option': 1,
                                'status': 1,
                                'status_detail': 'active',
                            })
                        sqs = sqs.filter(query)
            else:  # anonymous
                query = Q(
                    **{
                        'allow_anonymous_view': True,
                        'show_as_option': 1,
                        'status': 1,
                        'status_detail': 'active',
                    })
                sqs = sqs.filter(query)
        else:
            if user:
                if is_a_superuser:
                    # this is no-op. the .all().exclude(type='membership').models(Group) wouldn't work
                    #sqs = sqs.all()
                    sqs = sqs.filter(status=True)
                else:
                    if not user.is_anonymous:
                        # (status+status_detail+anon OR who_can_view__exact)
                        anon_query = Q(**{
                            'allow_anonymous_view': True,
                        })
                        user_query = Q(**{
                            'allow_user_view': True,
                        })
                        sec1_query = Q(
                            **{
                                'show_as_option': 1,
                                'status': 1,
                                'status_detail': 'active',
                            })
                        sec2_query = Q(
                            **{'who_can_view__exact': user.username})
                        query = reduce(operator.or_, [anon_query, user_query])
                        query = reduce(operator.and_, [sec1_query, query])
                        query = reduce(operator.or_, [query, sec2_query])
                        sqs = sqs.filter(query)
                    else:  # anonymous
                        query = Q(
                            **{
                                'allow_anonymous_view': True,
                                'show_as_option': 1,
                                'status': 1,
                                'status_detail': 'active',
                            })
                        sqs = sqs.filter(query)
            else:  # anonymous
                query = Q(
                    **{
                        'allow_anonymous_view': True,
                        'show_as_option': 1,
                        'status': 1,
                        'status_detail': 'active',
                    })
                sqs = sqs.filter(query)

        sqs = sqs.order_by('-create_dt')

        return sqs.models(self.model)
Beispiel #35
0
class LiveWhooshSearchQuerySetTestCase(TestCase):
    def setUp(self):
        super(LiveWhooshSearchQuerySetTestCase, self).setUp()

        # Stow.
        temp_path = os.path.join('tmp', 'test_whoosh_query')
        self.old_whoosh_path = getattr(settings, 'HAYSTACK_WHOOSH_PATH',
                                       temp_path)
        settings.HAYSTACK_WHOOSH_PATH = temp_path

        self.site = SearchSite()
        self.sb = SearchBackend(site=self.site)
        self.smmi = WhooshMockSearchIndex(MockModel, backend=self.sb)
        self.site.register(MockModel, WhooshMockSearchIndex)

        # Stow.
        import haystack
        self.old_debug = settings.DEBUG
        settings.DEBUG = True
        self.old_site = haystack.site
        haystack.site = self.site

        self.sb.setup()
        self.raw_whoosh = self.sb.index
        self.parser = QueryParser(self.sb.content_field_name,
                                  schema=self.sb.schema)
        self.sb.delete_index()

        self.sample_objs = []

        for i in xrange(1, 4):
            mock = MockModel()
            mock.id = i
            mock.author = 'daniel%s' % i
            mock.pub_date = date(2009, 2, 25) - timedelta(days=i)
            self.sample_objs.append(mock)

        self.sq = SearchQuery(backend=self.sb)
        self.sqs = SearchQuerySet(site=self.site)

    def tearDown(self):
        if os.path.exists(settings.HAYSTACK_WHOOSH_PATH):
            shutil.rmtree(settings.HAYSTACK_WHOOSH_PATH)

        settings.HAYSTACK_WHOOSH_PATH = self.old_whoosh_path

        import haystack
        haystack.site = self.old_site
        settings.DEBUG = self.old_debug

        super(LiveWhooshSearchQuerySetTestCase, self).tearDown()

    def test_various_searchquerysets(self):
        self.sb.update(self.smmi, self.sample_objs)

        sqs = self.sqs.filter(content='Index')
        self.assertEqual(sqs.query.build_query(), u'Index')
        self.assertEqual(len(sqs), 3)

        sqs = self.sqs.auto_query('Indexed!')
        self.assertEqual(sqs.query.build_query(), u"'Indexed!'")
        self.assertEqual(len(sqs), 3)

        sqs = self.sqs.auto_query('Indexed!').filter(
            pub_date__lte=date(2009, 8, 31))
        self.assertEqual(sqs.query.build_query(),
                         u"('Indexed!' AND pub_date:[TO 20090831T000000])")
        self.assertEqual(len(sqs), 3)

        sqs = self.sqs.auto_query('Indexed!').filter(
            pub_date__lte=date(2009, 2, 23))
        self.assertEqual(sqs.query.build_query(),
                         u"('Indexed!' AND pub_date:[TO 20090223T000000])")
        self.assertEqual(len(sqs), 2)

        sqs = self.sqs.auto_query('Indexed!').filter(
            pub_date__lte=date(2009, 2, 25)).filter(
                django_id__in=[1, 2]).exclude(name='daniel1')
        self.assertEqual(
            sqs.query.build_query(),
            u"('Indexed!' AND pub_date:[TO 20090225T000000] AND (django_id:\"1\" OR django_id:\"2\") AND NOT (name:daniel1))"
        )
        self.assertEqual(len(sqs), 1)

        sqs = self.sqs.auto_query('re-inker')
        self.assertEqual(sqs.query.build_query(), u"'re-inker'")
        self.assertEqual(len(sqs), 0)

        sqs = self.sqs.auto_query('0.7 wire')
        self.assertEqual(sqs.query.build_query(), u"('0.7' AND wire)")
        self.assertEqual(len(sqs), 0)

        sqs = self.sqs.auto_query("daler-rowney pearlescent 'bell bronze'")
        self.assertEqual(
            sqs.query.build_query(),
            u"(\"bell bronze\" AND 'daler-rowney' AND pearlescent)")
        self.assertEqual(len(sqs), 0)

        sqs = self.sqs.models(MockModel)
        self.assertEqual(sqs.query.build_query(), u'django_ct:core.mockmodel')
        self.assertEqual(len(sqs), 3)

    def test_all_regression(self):
        sqs = SearchQuerySet()
        self.assertEqual([result.pk for result in sqs], [])

        self.sb.update(self.smmi, self.sample_objs)
        self.assert_(self.sb.index.doc_count() > 0)

        sqs = SearchQuerySet()
        self.assertEqual(len(sqs), 3)
        self.assertEqual(sorted([result.pk for result in sqs]),
                         [u'1', u'2', u'3'])

        try:
            sqs = repr(SearchQuerySet())
        except:
            self.fail()

    def test_regression_space_query(self):
        self.sb.update(self.smmi, self.sample_objs)
        self.assert_(self.sb.index.doc_count() > 0)

        sqs = SearchQuerySet().auto_query(" ")
        self.assertEqual(len(sqs), 3)
        sqs = SearchQuerySet().filter(content=" ")
        self.assertEqual(len(sqs), 0)

    def test_iter(self):
        self.sb.update(self.smmi, self.sample_objs)

        backends.reset_search_queries()
        self.assertEqual(len(backends.queries), 0)
        sqs = self.sqs.auto_query('Indexed!')
        results = [int(result.pk) for result in sqs]
        self.assertEqual(sorted(results), [1, 2, 3])
        self.assertEqual(len(backends.queries), 1)

    def test_slice(self):
        self.sb.update(self.smmi, self.sample_objs)

        backends.reset_search_queries()
        self.assertEqual(len(backends.queries), 0)
        results = self.sqs.auto_query('Indexed!')
        self.assertEqual(sorted([int(result.pk) for result in results[1:3]]),
                         [1, 2])
        self.assertEqual(len(backends.queries), 1)

        backends.reset_search_queries()
        self.assertEqual(len(backends.queries), 0)
        results = self.sqs.auto_query('Indexed!')
        self.assertEqual(int(results[0].pk), 1)
        self.assertEqual(len(backends.queries), 1)

    def test_manual_iter(self):
        self.sb.update(self.smmi, self.sample_objs)
        results = self.sqs.auto_query('Indexed!')

        backends.reset_search_queries()
        self.assertEqual(len(backends.queries), 0)
        results = [int(result.pk) for result in results._manual_iter()]
        self.assertEqual(sorted(results), [1, 2, 3])
        self.assertEqual(len(backends.queries), 1)

    def test_fill_cache(self):
        self.sb.update(self.smmi, self.sample_objs)

        backends.reset_search_queries()
        self.assertEqual(len(backends.queries), 0)
        results = self.sqs.auto_query('Indexed!')
        self.assertEqual(len(results._result_cache), 0)
        self.assertEqual(len(backends.queries), 0)
        results._fill_cache(0, 10)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 3)
        self.assertEqual(len(backends.queries), 1)
        results._fill_cache(10, 20)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 3)
        self.assertEqual(len(backends.queries), 2)

    def test_cache_is_full(self):
        self.sb.update(self.smmi, self.sample_objs)

        backends.reset_search_queries()
        self.assertEqual(len(backends.queries), 0)
        self.assertEqual(self.sqs._cache_is_full(), False)
        results = self.sqs.auto_query('Indexed!')
        fire_the_iterator_and_fill_cache = [result for result in results]
        self.assertEqual(results._cache_is_full(), True)
        self.assertEqual(len(backends.queries), 1)

    def test_count(self):
        more_samples = []

        for i in xrange(1, 50):
            mock = MockModel()
            mock.id = i
            mock.author = 'daniel%s' % i
            mock.pub_date = date(2009, 2, 25) - timedelta(days=i)
            more_samples.append(mock)

        self.sb.update(self.smmi, more_samples)

        backends.reset_search_queries()
        self.assertEqual(len(backends.queries), 0)
        results = self.sqs.all()
        self.assertEqual(len(results), 49)
        self.assertEqual(results._cache_is_full(), False)
        self.assertEqual(len(backends.queries), 1)
class InterfaceTestCase(TestCase):
    """
    Tests the interface of Xapian-Haystack.

    Tests related to usability and expected behavior
    go here.
    """

    def setUp(self):
        super(InterfaceTestCase, self).setUp()

        types_names = ['book', 'magazine', 'article']
        texts = ['This is a huge text',
                 'This is a medium text',
                 'This is a small text']
        dates = [datetime.date(year=2010, month=1, day=1),
                 datetime.date(year=2010, month=2, day=1),
                 datetime.date(year=2010, month=3, day=1)]

        summaries = ['This is a huge corrup\xe7\xe3o summary',
                     'This is a medium summary',
                     'This is a small summary']

        for i in range(1, 13):
            doc = Document()
            doc.type_name = types_names[i % 3]
            doc.number = i * 2
            doc.name = "%s %d" % (doc.type_name, doc.number)
            doc.date = dates[i % 3]

            doc.summary = summaries[i % 3]
            doc.text = texts[i % 3]
            doc.save()

        self.index = DocumentIndex()
        self.ui = connections['default'].get_unified_index()
        self.ui.build(indexes=[self.index])

        self.backend = connections['default'].get_backend()
        self.backend.update(self.index, Document.objects.all())

        self.queryset = SearchQuerySet()

    def tearDown(self):
        Document.objects.all().delete()
        #self.backend.clear()
        super(InterfaceTestCase, self).tearDown()

    def test_count(self):
        self.assertEqual(self.queryset.count(), Document.objects.count())

    def test_content_search(self):
        result = self.queryset.filter(content='medium this')
        self.assertEqual(sorted(pks(result)),
                         pks(Document.objects.all()))

        # documents with "medium" AND "this" have higher score
        self.assertEqual(pks(result)[:4], [1, 4, 7, 10])

    def test_field_search(self):
        self.assertEqual(pks(self.queryset.filter(name__contains='8')), [4])
        self.assertEqual(pks(self.queryset.filter(type_name='book')),
                         pks(Document.objects.filter(type_name='book')))

        self.assertEqual(pks(self.queryset.filter(text__contains='text huge')),
                         pks(Document.objects.filter(text__contains='text huge')))

    def test_field_contains(self):
        self.assertEqual(pks(self.queryset.filter(summary__contains='huge')),
                         pks(Document.objects.filter(summary__contains='huge')))

        result = self.queryset.filter(summary__contains='huge summary')
        self.assertEqual(sorted(pks(result)),
                         pks(Document.objects.all()))

        # documents with "huge" AND "summary" have higher score
        self.assertEqual(pks(result)[:4], [3, 6, 9, 12])

    def test_field_exact(self):
        self.assertEqual(pks(self.queryset.filter(name__exact='8')), [])
        self.assertEqual(pks(self.queryset.filter(name__exact='magazine 2')), [1])

    def test_content_exact(self):
        self.assertEqual(pks(self.queryset.filter(content__exact='huge')), [])

    def test_content_and(self):
        self.assertEqual(pks(self.queryset.filter(content='huge').filter(summary='medium')), [])

        self.assertEqual(len(self.queryset.filter(content='huge this')), 12)
        self.assertEqual(len(self.queryset.filter(content='huge this').filter(summary__contains='huge')), 4)

    def test_content_or(self):
        self.assertEqual(len(self.queryset.filter(content='huge medium')), 8)
        self.assertEqual(len(self.queryset.filter(content='huge medium small')), 12)

    def test_field_and(self):
        self.assertEqual(pks(self.queryset.filter(name='8').filter(name='4')), [])

    def test_field_or(self):
        self.assertEqual(pks(self.queryset.filter(name__contains='8 4')), [2, 4])

    def test_field_in(self):
        self.assertEqual(set(pks(self.queryset.filter(name__in=['magazine 2', 'article 4']))),
                         set(pks(Document.objects.filter(name__in=['magazine 2', 'article 4']))))

        self.assertEqual(pks(self.queryset.filter(number__in=[4])),
                         pks(Document.objects.filter(number__in=[4])))

        self.assertEqual(pks(self.queryset.filter(number__in=[4, 8])),
                         pks(Document.objects.filter(number__in=[4, 8])))

    def test_private_fields(self):
        self.assertEqual(pks(self.queryset.filter(django_id=4)),
                         pks(Document.objects.filter(id__in=[4])))
        self.assertEqual(pks(self.queryset.filter(django_id__in=[2, 4])),
                         pks(Document.objects.filter(id__in=[2, 4])))

        self.assertEqual(set(pks(self.queryset.models(Document))),
                         set(pks(Document.objects.all())))

    def test_field_startswith(self):
        self.assertEqual(len(self.queryset.filter(name__startswith='magaz')), 4)
        self.assertEqual(set(pks(self.queryset.filter(summary__startswith='This is a huge'))),
                         set(pks(Document.objects.filter(summary__startswith='This is a huge'))))

    def test_auto_query(self):
        # todo: improve to query text only.
        self.assertEqual(set(pks(self.queryset.auto_query("huge OR medium"))),
                         set(pks(Document.objects.filter(Q(text__contains="huge") |
                                                         Q(text__contains="medium")))))

        self.assertEqual(set(pks(self.queryset.auto_query("huge AND medium"))),
                         set(pks(Document.objects.filter(Q(text__contains="huge") &
                                                         Q(text__contains="medium")))))

        self.assertEqual(set(pks(self.queryset.auto_query("text:huge text:-this"))),
                         set(pks(Document.objects.filter(Q(text__contains="huge") &
                                                         ~Q(text__contains="this")))))

        self.assertEqual(len(self.queryset.filter(name=AutoQuery("8 OR 4"))), 2)
        self.assertEqual(len(self.queryset.filter(name=AutoQuery("8 AND 4"))), 0)

    def test_value_range(self):
        self.assertEqual(set(pks(self.queryset.filter(number__lt=3))),
                         set(pks(Document.objects.filter(number__lt=3))))

        self.assertEqual(set(pks(self.queryset.filter(django_id__gte=6))),
                         set(pks(Document.objects.filter(id__gte=6))))

    def test_date_range(self):
        date = datetime.date(year=2010, month=2, day=1)
        self.assertEqual(set(pks(self.queryset.filter(date__gte=date))),
                         set(pks(Document.objects.filter(date__gte=date))))

        date = datetime.date(year=2010, month=3, day=1)
        self.assertEqual(set(pks(self.queryset.filter(date__lte=date))),
                         set(pks(Document.objects.filter(date__lte=date))))

    def test_order_by(self):
        # private order
        self.assertEqual(pks(self.queryset.order_by("-django_id")),
                         pks(Document.objects.order_by("-id")))

        # value order
        self.assertEqual(pks(self.queryset.order_by("number")),
                         pks(Document.objects.order_by("number")))

        # text order
        self.assertEqual(pks(self.queryset.order_by("summary")),
                         pks(Document.objects.order_by("summary")))

        # date order
        self.assertEqual(pks(self.queryset.order_by("-date")),
                         pks(Document.objects.order_by("-date")))

    def test_non_ascii_search(self):
        """
        Regression test for #119.
        """
        self.assertEqual(pks(self.queryset.filter(content='corrup\xe7\xe3o')),
                         pks(Document.objects.filter(summary__contains='corrup\xe7\xe3o')))

    def test_multi_values_exact_search(self):
        """
        Regression test for #103
        """
        self.assertEqual(len(self.queryset.filter(tags__exact='tag')), 12)
        self.assertEqual(len(self.queryset.filter(tags__exact='tag-test')), 8)
        self.assertEqual(len(self.queryset.filter(tags__exact='tag-test-test')), 4)
Beispiel #37
0
class SearchQuerySetTestCase(TestCase):
    fixtures = ["base_data.json", "bulk_data.json"]

    def setUp(self):
        super(SearchQuerySetTestCase, self).setUp()

        # Stow.
        self.old_unified_index = connections["default"]._index
        self.ui = UnifiedIndex()
        self.bmmsi = BasicMockModelSearchIndex()
        self.cpkmmsi = CharPKMockModelSearchIndex()
        self.uuidmmsi = SimpleMockUUIDModelIndex()
        self.ui.build(indexes=[self.bmmsi, self.cpkmmsi, self.uuidmmsi])
        connections["default"]._index = self.ui

        # Update the "index".
        backend = connections["default"].get_backend()
        backend.clear()
        backend.update(self.bmmsi, MockModel.objects.all())

        self.msqs = SearchQuerySet()

        # Stow.
        reset_search_queries()

    def tearDown(self):
        # Restore.
        connections["default"]._index = self.old_unified_index
        super(SearchQuerySetTestCase, self).tearDown()

    def test_len(self):
        self.assertEqual(len(self.msqs), 23)

    def test_repr(self):
        reset_search_queries()
        self.assertEqual(len(connections["default"].queries), 0)
        self.assertRegexpMatches(
            repr(self.msqs),
            r"^<SearchQuerySet: query=<test_haystack.mocks.MockSearchQuery object"
            r" at 0x[0-9A-Fa-f]+>, using=None>$",
        )

    def test_iter(self):
        reset_search_queries()
        self.assertEqual(len(connections["default"].queries), 0)
        msqs = self.msqs.all()
        results = [int(res.pk) for res in iter(msqs)]
        self.assertEqual(results, [res.pk for res in MOCK_SEARCH_RESULTS[:23]])
        self.assertEqual(len(connections["default"].queries), 3)

    def test_slice(self):
        reset_search_queries()
        self.assertEqual(len(connections["default"].queries), 0)
        results = self.msqs.all()
        self.assertEqual(
            [int(res.pk) for res in results[1:11]],
            [res.pk for res in MOCK_SEARCH_RESULTS[1:11]],
        )
        self.assertEqual(len(connections["default"].queries), 1)

        reset_search_queries()
        self.assertEqual(len(connections["default"].queries), 0)
        results = self.msqs.all()
        self.assertEqual(int(results[22].pk), MOCK_SEARCH_RESULTS[22].pk)
        self.assertEqual(len(connections["default"].queries), 1)

    def test_manual_iter(self):
        results = self.msqs.all()

        reset_search_queries()
        self.assertEqual(len(connections["default"].queries), 0)

        check = [result.pk for result in results._manual_iter()]
        self.assertEqual(
            check,
            [
                "1",
                "2",
                "3",
                "4",
                "5",
                "6",
                "7",
                "8",
                "9",
                "10",
                "11",
                "12",
                "13",
                "14",
                "15",
                "16",
                "17",
                "18",
                "19",
                "20",
                "21",
                "22",
                "23",
            ],
        )

        self.assertEqual(len(connections["default"].queries), 3)

        reset_search_queries()
        self.assertEqual(len(connections["default"].queries), 0)

        # Test to ensure we properly fill the cache, even if we get fewer
        # results back (not a handled model) than the hit count indicates.
        # This will hang indefinitely if broken.

        # CharPK testing
        old_ui = self.ui
        self.ui.build(indexes=[self.cpkmmsi])
        connections["default"]._index = self.ui
        self.cpkmmsi.update()

        results = self.msqs.all()
        loaded = [result.pk for result in results._manual_iter()]
        self.assertEqual(loaded, ["sometext", "1234"])
        self.assertEqual(len(connections["default"].queries), 1)

        # UUID testing
        self.ui.build(indexes=[self.uuidmmsi])
        connections["default"]._index = self.ui
        self.uuidmmsi.update()

        results = self.msqs.all()
        loaded = [result.pk for result in results._manual_iter()]
        self.assertEqual(
            loaded,
            [
                "53554c58-7051-4350-bcc9-dad75eb248a9",
                "77554c58-7051-4350-bcc9-dad75eb24888",
            ],
        )

        connections["default"]._index = old_ui

    def test_cache_is_full(self):
        reset_search_queries()
        self.assertEqual(len(connections["default"].queries), 0)
        self.assertEqual(self.msqs._cache_is_full(), False)
        results = self.msqs.all()
        fire_the_iterator_and_fill_cache = list(results)
        self.assertEqual(23, len(fire_the_iterator_and_fill_cache))
        self.assertEqual(results._cache_is_full(), True)
        self.assertEqual(len(connections["default"].queries), 4)

    def test_all(self):
        sqs = self.msqs.all()
        self.assertTrue(isinstance(sqs, SearchQuerySet))

    def test_filter(self):
        sqs = self.msqs.filter(content="foo")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 1)

    def test_exclude(self):
        sqs = self.msqs.exclude(content="foo")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 1)

    def test_order_by(self):
        sqs = self.msqs.order_by("foo")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertTrue("foo" in sqs.query.order_by)

    def test_models(self):
        # Stow.
        old_unified_index = connections["default"]._index
        ui = UnifiedIndex()
        bmmsi = BasicMockModelSearchIndex()
        bammsi = BasicAnotherMockModelSearchIndex()
        ui.build(indexes=[bmmsi, bammsi])
        connections["default"]._index = ui

        msqs = SearchQuerySet()

        sqs = msqs.all()
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.models), 0)

        sqs = msqs.models(MockModel)
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.models), 1)

        sqs = msqs.models(MockModel, AnotherMockModel)
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.models), 2)

        # This will produce a warning.
        ui.build(indexes=[bmmsi])
        sqs = msqs.models(AnotherMockModel)
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.models), 1)

    def test_result_class(self):
        sqs = self.msqs.all()
        self.assertTrue(issubclass(sqs.query.result_class, SearchResult))

        # Custom class.
        class IttyBittyResult(object):
            pass

        sqs = self.msqs.result_class(IttyBittyResult)
        self.assertTrue(issubclass(sqs.query.result_class, IttyBittyResult))

        # Reset to default.
        sqs = self.msqs.result_class(None)
        self.assertTrue(issubclass(sqs.query.result_class, SearchResult))

    def test_boost(self):
        sqs = self.msqs.boost("foo", 10)
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.boost.keys()), 1)

    def test_highlight(self):
        sqs = self.msqs.highlight()
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(sqs.query.highlight, True)

    def test_spelling_override(self):
        sqs = self.msqs.filter(content="not the spellchecking query")
        self.assertEqual(sqs.query.spelling_query, None)
        sqs = self.msqs.set_spelling_query("override")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(sqs.query.spelling_query, "override")

    def test_spelling_suggestions(self):
        # Test the case where spelling support is disabled.
        sqs = self.msqs.filter(content="Indx")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(sqs.spelling_suggestion(), None)
        self.assertEqual(sqs.spelling_suggestion("indexy"), None)

    def test_raw_search(self):
        self.assertEqual(len(self.msqs.raw_search("foo")), 23)
        self.assertEqual(
            len(
                self.msqs.raw_search(
                    "(content__exact:hello AND content__exact:world)")),
            23,
        )

    def test_load_all(self):
        # Models with character primary keys.
        sqs = SearchQuerySet()
        sqs.query.backend = CharPKMockSearchBackend("charpk")
        results = sqs.load_all().all()
        self.assertEqual(len(results._result_cache), 0)
        results._fill_cache(0, 2)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 2)

        # Models with uuid primary keys.
        sqs = SearchQuerySet()
        sqs.query.backend = UUIDMockSearchBackend("uuid")
        results = sqs.load_all().all()
        self.assertEqual(len(results._result_cache), 0)
        results._fill_cache(0, 2)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 2)

        # If nothing is handled, you get nothing.
        old_ui = connections["default"]._index
        ui = UnifiedIndex()
        ui.build(indexes=[])
        connections["default"]._index = ui

        sqs = self.msqs.load_all()
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs), 0)

        connections["default"]._index = old_ui

        # For full tests, see the solr_backend.

    def test_load_all_read_queryset(self):
        # Stow.
        old_ui = connections["default"]._index
        ui = UnifiedIndex()
        gafmmsi = GhettoAFifthMockModelSearchIndex()
        ui.build(indexes=[gafmmsi])
        connections["default"]._index = ui
        gafmmsi.update()

        sqs = SearchQuerySet()
        results = sqs.load_all().all()
        results.query.backend = ReadQuerySetMockSearchBackend("default")
        results._fill_cache(0, 2)

        # The deleted result isn't returned
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 1)

        # Register a SearchIndex with a read_queryset that returns deleted items
        rqstsi = TextReadQuerySetTestSearchIndex()
        ui.build(indexes=[rqstsi])
        rqstsi.update()

        sqs = SearchQuerySet()
        results = sqs.load_all().all()
        results.query.backend = ReadQuerySetMockSearchBackend("default")
        results._fill_cache(0, 2)

        # Both the deleted and not deleted items are returned
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 2)

        # Restore.
        connections["default"]._index = old_ui

    def test_auto_query(self):
        sqs = self.msqs.auto_query("test search -stuff")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(
            repr(sqs.query.query_filter),
            "<SQ: AND content__content=test search -stuff>",
        )

        sqs = self.msqs.auto_query('test "my thing" search -stuff')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(
            repr(sqs.query.query_filter),
            '<SQ: AND content__content=test "my thing" search -stuff>',
        )

        sqs = self.msqs.auto_query(
            "test \"my thing\" search 'moar quotes' -stuff")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(
            repr(sqs.query.query_filter),
            "<SQ: AND content__content=test \"my thing\" search 'moar quotes' -stuff>",
        )

        sqs = self.msqs.auto_query(
            'test "my thing" search \'moar quotes\' "foo -stuff')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(
            repr(sqs.query.query_filter),
            '<SQ: AND content__content=test "my thing" search \'moar quotes\' "foo -stuff>',
        )

        sqs = self.msqs.auto_query("test - stuff")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(repr(sqs.query.query_filter),
                         "<SQ: AND content__content=test - stuff>")

        # Ensure bits in exact matches get escaped properly as well.
        sqs = self.msqs.auto_query('"pants:rule"')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(repr(sqs.query.query_filter),
                         '<SQ: AND content__content="pants:rule">')

        # Now with a different fieldname
        sqs = self.msqs.auto_query("test search -stuff", fieldname="title")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(repr(sqs.query.query_filter),
                         "<SQ: AND title__content=test search -stuff>")

        sqs = self.msqs.auto_query('test "my thing" search -stuff',
                                   fieldname="title")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(
            repr(sqs.query.query_filter),
            '<SQ: AND title__content=test "my thing" search -stuff>',
        )

    def test_count(self):
        self.assertEqual(self.msqs.count(), 23)

    def test_facet_counts(self):
        self.assertEqual(self.msqs.facet_counts(), {})

    def test_best_match(self):
        self.assertTrue(isinstance(self.msqs.best_match(), SearchResult))

    def test_latest(self):
        self.assertTrue(isinstance(self.msqs.latest("pub_date"), SearchResult))

    def test_more_like_this(self):
        mock = MockModel()
        mock.id = 1

        self.assertEqual(len(self.msqs.more_like_this(mock)), 23)

    def test_facets(self):
        sqs = self.msqs.facet("foo")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.facets), 1)

        sqs2 = self.msqs.facet("foo").facet("bar")
        self.assertTrue(isinstance(sqs2, SearchQuerySet))
        self.assertEqual(len(sqs2.query.facets), 2)

    def test_date_facets(self):
        try:
            sqs = self.msqs.date_facet(
                "foo",
                start_date=datetime.date(2008, 2, 25),
                end_date=datetime.date(2009, 2, 25),
                gap_by="smarblaph",
            )
            self.fail()
        except FacetingError as e:
            self.assertEqual(
                str(e),
                "The gap_by ('smarblaph') must be one of the following: year, month, day, hour, minute, second.",
            )

        sqs = self.msqs.date_facet(
            "foo",
            start_date=datetime.date(2008, 2, 25),
            end_date=datetime.date(2009, 2, 25),
            gap_by="month",
        )
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.date_facets), 1)

        sqs2 = self.msqs.date_facet(
            "foo",
            start_date=datetime.date(2008, 2, 25),
            end_date=datetime.date(2009, 2, 25),
            gap_by="month",
        ).date_facet(
            "bar",
            start_date=datetime.date(2007, 2, 25),
            end_date=datetime.date(2009, 2, 25),
            gap_by="year",
        )
        self.assertTrue(isinstance(sqs2, SearchQuerySet))
        self.assertEqual(len(sqs2.query.date_facets), 2)

    def test_query_facets(self):
        sqs = self.msqs.query_facet("foo", "[bar TO *]")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_facets), 1)

        sqs2 = self.msqs.query_facet("foo", "[bar TO *]").query_facet(
            "bar", "[100 TO 499]")
        self.assertTrue(isinstance(sqs2, SearchQuerySet))
        self.assertEqual(len(sqs2.query.query_facets), 2)

        # Test multiple query facets on a single field
        sqs3 = (self.msqs.query_facet("foo", "[bar TO *]").query_facet(
            "bar", "[100 TO 499]").query_facet("foo", "[1000 TO 1499]"))
        self.assertTrue(isinstance(sqs3, SearchQuerySet))
        self.assertEqual(len(sqs3.query.query_facets), 3)

    def test_stats(self):
        sqs = self.msqs.stats_facet("foo", "bar")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.stats), 1)

        sqs2 = self.msqs.stats_facet("foo", "bar").stats_facet("foo", "baz")
        self.assertTrue(isinstance(sqs2, SearchQuerySet))
        self.assertEqual(len(sqs2.query.stats), 1)

        sqs3 = self.msqs.stats_facet("foo", "bar").stats_facet("moof", "baz")
        self.assertTrue(isinstance(sqs3, SearchQuerySet))
        self.assertEqual(len(sqs3.query.stats), 2)

    def test_narrow(self):
        sqs = self.msqs.narrow("foo:moof")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.narrow_queries), 1)

    def test_clone(self):
        results = self.msqs.filter(foo="bar", foo__lt="10")

        clone = results._clone()
        self.assertTrue(isinstance(clone, SearchQuerySet))
        self.assertEqual(str(clone.query), str(results.query))
        self.assertEqual(clone._result_cache, [])
        self.assertEqual(clone._result_count, None)
        self.assertEqual(clone._cache_full, False)
        self.assertEqual(clone._using, results._using)

    def test_using(self):
        sqs = SearchQuerySet(using="default")
        self.assertNotEqual(sqs.query, None)
        self.assertEqual(sqs.query._using, "default")

    def test_chaining(self):
        sqs = self.msqs.filter(content="foo")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 1)

        # A second instance should inherit none of the changes from above.
        sqs = self.msqs.filter(content="bar")
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 1)

    def test_none(self):
        sqs = self.msqs.none()
        self.assertTrue(isinstance(sqs, EmptySearchQuerySet))
        self.assertEqual(len(sqs), 0)

    def test___and__(self):
        sqs1 = self.msqs.filter(content="foo")
        sqs2 = self.msqs.filter(content="bar")
        sqs = sqs1 & sqs2

        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 2)

    def test___or__(self):
        sqs1 = self.msqs.filter(content="foo")
        sqs2 = self.msqs.filter(content="bar")
        sqs = sqs1 | sqs2

        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 2)

    def test_and_or(self):
        """
        Combining AND queries with OR should give
            AND(OR(a, b), OR(c, d))
        """
        sqs1 = self.msqs.filter(content="foo").filter(content="oof")
        sqs2 = self.msqs.filter(content="bar").filter(content="rab")
        sqs = sqs1 | sqs2

        self.assertEqual(sqs.query.query_filter.connector, "OR")
        self.assertEqual(repr(sqs.query.query_filter.children[0]),
                         repr(sqs1.query.query_filter))
        self.assertEqual(repr(sqs.query.query_filter.children[1]),
                         repr(sqs2.query.query_filter))

    def test_or_and(self):
        """
        Combining OR queries with AND should give
            OR(AND(a, b), AND(c, d))
        """
        sqs1 = self.msqs.filter(content="foo").filter_or(content="oof")
        sqs2 = self.msqs.filter(content="bar").filter_or(content="rab")
        sqs = sqs1 & sqs2

        self.assertEqual(sqs.query.query_filter.connector, "AND")
        self.assertEqual(repr(sqs.query.query_filter.children[0]),
                         repr(sqs1.query.query_filter))
        self.assertEqual(repr(sqs.query.query_filter.children[1]),
                         repr(sqs2.query.query_filter))
 def test_index_template(self):
     r = SearchQuerySet().all()
     self.assertTrue(r.count())
     self.assertEquals(r.filter(text="bicicletas").count(), 1)
Beispiel #39
0
def _query_results(query, person):
    """
    Actually build the query results for this person.

    Make sure any result.content_type values are reflected in RESULT_TYPE_DISPLAY for display to the user.
    """
    if len(query) < 2:
        return []

    query = query.replace('@sfu.ca', '') # hack to make email addresses searchable as userids
    query = Clean(query)

    # offerings person was a member of (coredata.CourseOffering)
    if person:
        members = Member.objects.filter(person=person).exclude(role='DROP').select_related('offering')
        offering_slugs = set(m.offering.slug for m in members)
        offering_results = SearchQuerySet().models(CourseOffering).filter(text=query) # offerings that match the query
        offering_results = offering_results.filter(slug__in=offering_slugs) # ... and this person was in
    else:
        members = []
        offering_results = []

    # pages this person can view (pages.Page)
    page_acl = set(['ALL'])
    for m in members:
        # builds a set of offering_slug+"_"+acl_value strings, which will match the permission_key field in the index
        member_acl = set("%s_%s" % (m.offering.slug, acl) for acl in ACL_ROLES[m.role] if acl != 'ALL')
        page_acl |= member_acl

    page_results = SearchQuerySet().models(Page).filter(text=query) # pages that match the query
    page_results = page_results.filter(permission_key__in=page_acl) # ... and are visible to this user

    # discussion this person can view (discussion.DiscussionTopic)
    if person:
        discuss_results = SearchQuerySet().models(DiscussionTopic).filter(text=query) # discussions that match the query
        discuss_results = discuss_results.filter(slug__in=offering_slugs) # ... and this person was in
    else:
        discuss_results = []

    # students taught by instructor (coredata.Member)
    instr_members = Member.objects.filter(person=person, role__in=['INST','TA']).exclude(offering__component='CAN') \
        .select_related('offering')
    if person and instr_members:
        offering_slugs = set(m.offering.slug for m in instr_members)
        member_results = SearchQuerySet().models(Member).filter(text=query) # members that match the query
        member_results = member_results.filter(offering_slug__in=offering_slugs) # ... and this person was the instructor for
        member_results = member_results.load_all()
    else:
        member_results = []

    # combine and limit to best results
    results = itertools.chain(
        offering_results[:MAX_RESULTS],
        page_results[:MAX_RESULTS],
        member_results[:MAX_RESULTS],
        discuss_results[:MAX_RESULTS],
        )
    results = (r for r in results if r is not None)
    results = list(results)
    results.sort(key=lambda result: -result.score)
    results = results[:MAX_RESULTS] # (list before this could be n*MAX_RESULTS long)

    return results
Beispiel #40
0
class LiveSolrSearchQuerySetTestCase(TestCase):
    """Used to test actual implementation details of the SearchQuerySet."""
    fixtures = ['bulk_data.json']

    def setUp(self):
        super(LiveSolrSearchQuerySetTestCase, self).setUp()

        # Stow.
        self.old_debug = settings.DEBUG
        settings.DEBUG = True
        self.old_ui = connections['default'].get_unified_index()
        self.ui = UnifiedIndex()
        self.smmi = SolrMockSearchIndex()
        self.ui.build(indexes=[self.smmi])
        connections['default']._index = self.ui

        self.sqs = SearchQuerySet()
        self.rsqs = RelatedSearchQuerySet()

        # Ugly but not constantly reindexing saves us almost 50% runtime.
        global lssqstc_all_loaded

        if lssqstc_all_loaded is None:
            print 'Reloading data...'
            lssqstc_all_loaded = True

            # Wipe it clean.
            clear_solr_index()

            # Force indexing of the content.
            self.smmi.update()

    def tearDown(self):
        # Restore.
        connections['default']._index = self.old_ui
        settings.DEBUG = self.old_debug
        super(LiveSolrSearchQuerySetTestCase, self).tearDown()

    def test_load_all(self):
        sqs = self.sqs.load_all()
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertTrue(len(sqs) > 0)
        self.assertEqual(
            sqs[0].object.foo,
            u"Registering indexes in Haystack is very similar to registering models and ``ModelAdmin`` classes in the `Django admin site`_.  If you want to override the default indexing behavior for your model you can specify your own ``SearchIndex`` class.  This is useful for ensuring that future-dated or non-live content is not indexed and searchable. Our ``Note`` model has a ``pub_date`` field, so let's update our code to include our own ``SearchIndex`` to exclude indexing future-dated notes:"
        )

    def test_iter(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        sqs = self.sqs.all()
        results = [int(result.pk) for result in sqs]
        self.assertEqual(results, range(1, 24))
        self.assertEqual(len(connections['default'].queries), 3)

    def test_slice(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        results = self.sqs.all()
        self.assertEqual([int(result.pk) for result in results[1:11]],
                         [2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
        self.assertEqual(len(connections['default'].queries), 1)

        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        results = self.sqs.all()
        self.assertEqual(int(results[21].pk), 22)
        self.assertEqual(len(connections['default'].queries), 1)

    def test_count(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        sqs = self.sqs.all()
        self.assertEqual(sqs.count(), 23)
        self.assertEqual(sqs.count(), 23)
        self.assertEqual(len(sqs), 23)
        self.assertEqual(sqs.count(), 23)
        # Should only execute one query to count the length of the result set.
        self.assertEqual(len(connections['default'].queries), 1)

    def test_manual_iter(self):
        results = self.sqs.all()

        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        results = [int(result.pk) for result in results._manual_iter()]
        self.assertEqual(results, range(1, 24))
        self.assertEqual(len(connections['default'].queries), 3)

    def test_fill_cache(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        results = self.sqs.all()
        self.assertEqual(len(results._result_cache), 0)
        self.assertEqual(len(connections['default'].queries), 0)
        results._fill_cache(0, 10)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 10)
        self.assertEqual(len(connections['default'].queries), 1)
        results._fill_cache(10, 20)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 20)
        self.assertEqual(len(connections['default'].queries), 2)

    def test_cache_is_full(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        self.assertEqual(self.sqs._cache_is_full(), False)
        results = self.sqs.all()
        fire_the_iterator_and_fill_cache = [result for result in results]
        self.assertEqual(results._cache_is_full(), True)
        self.assertEqual(len(connections['default'].queries), 3)

    def test___and__(self):
        sqs1 = self.sqs.filter(content='foo')
        sqs2 = self.sqs.filter(content='bar')
        sqs = sqs1 & sqs2

        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 2)
        self.assertEqual(sqs.query.build_query(), u'(foo AND bar)')

        # Now for something more complex...
        sqs3 = self.sqs.exclude(
            title='moof').filter(SQ(content='foo') | SQ(content='baz'))
        sqs4 = self.sqs.filter(content='bar')
        sqs = sqs3 & sqs4

        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 3)
        self.assertEqual(sqs.query.build_query(),
                         u'(NOT (title:moof) AND (foo OR baz) AND bar)')

    def test___or__(self):
        sqs1 = self.sqs.filter(content='foo')
        sqs2 = self.sqs.filter(content='bar')
        sqs = sqs1 | sqs2

        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 2)
        self.assertEqual(sqs.query.build_query(), u'(foo OR bar)')

        # Now for something more complex...
        sqs3 = self.sqs.exclude(
            title='moof').filter(SQ(content='foo') | SQ(content='baz'))
        sqs4 = self.sqs.filter(content='bar').models(MockModel)
        sqs = sqs3 | sqs4

        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 2)
        self.assertEqual(sqs.query.build_query(),
                         u'((NOT (title:moof) AND (foo OR baz)) OR bar)')

    def test_auto_query(self):
        # Ensure bits in exact matches get escaped properly as well.
        # This will break horrifically if escaping isn't working.
        sqs = self.sqs.auto_query('"pants:rule"')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(repr(sqs.query.query_filter),
                         '<SQ: AND content__contains="pants:rule">')
        self.assertEqual(sqs.query.build_query(), u'"pants\\:rule"')
        self.assertEqual(len(sqs), 0)

    # Regressions

    def test_regression_proper_start_offsets(self):
        sqs = self.sqs.filter(text='index')
        self.assertNotEqual(sqs.count(), 0)

        id_counts = {}

        for item in sqs:
            if item.id in id_counts:
                id_counts[item.id] += 1
            else:
                id_counts[item.id] = 1

        for key, value in id_counts.items():
            if value > 1:
                self.fail(
                    "Result with id '%s' seen more than once in the results." %
                    key)

    def test_regression_raw_search_breaks_slicing(self):
        sqs = self.sqs.raw_search('text: index')
        page_1 = [result.pk for result in sqs[0:10]]
        page_2 = [result.pk for result in sqs[10:20]]

        for pk in page_2:
            if pk in page_1:
                self.fail(
                    "Result with id '%s' seen more than once in the results." %
                    pk)

    # RelatedSearchQuerySet Tests

    def test_related_load_all(self):
        sqs = self.rsqs.load_all()
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertTrue(len(sqs) > 0)
        self.assertEqual(
            sqs[0].object.foo,
            u"Registering indexes in Haystack is very similar to registering models and ``ModelAdmin`` classes in the `Django admin site`_.  If you want to override the default indexing behavior for your model you can specify your own ``SearchIndex`` class.  This is useful for ensuring that future-dated or non-live content is not indexed and searchable. Our ``Note`` model has a ``pub_date`` field, so let's update our code to include our own ``SearchIndex`` to exclude indexing future-dated notes:"
        )

    def test_related_load_all_queryset(self):
        sqs = self.rsqs.load_all()
        self.assertEqual(len(sqs._load_all_querysets), 0)

        sqs = sqs.load_all_queryset(MockModel,
                                    MockModel.objects.filter(id__gt=1))
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs._load_all_querysets), 1)
        self.assertEqual([obj.object.id for obj in sqs], range(2, 24))

        sqs = sqs.load_all_queryset(MockModel,
                                    MockModel.objects.filter(id__gt=10))
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs._load_all_querysets), 1)
        self.assertEqual([obj.object.id for obj in sqs], range(11, 24))
        self.assertEqual([obj.object.id for obj in sqs[10:20]], [21, 22, 23])

    def test_related_iter(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        sqs = self.rsqs.all()
        results = [int(result.pk) for result in sqs]
        self.assertEqual(results, range(1, 24))
        self.assertEqual(len(connections['default'].queries), 4)

    def test_related_slice(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        results = self.rsqs.all()
        self.assertEqual([int(result.pk) for result in results[1:11]],
                         [2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
        self.assertEqual(len(connections['default'].queries), 3)

        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        results = self.rsqs.all()
        self.assertEqual(int(results[21].pk), 22)
        self.assertEqual(len(connections['default'].queries), 4)

        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        results = self.rsqs.all()
        self.assertEqual([int(result.pk) for result in results[20:30]],
                         [21, 22, 23])
        self.assertEqual(len(connections['default'].queries), 4)

    def test_related_manual_iter(self):
        results = self.rsqs.all()

        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        results = [int(result.pk) for result in results._manual_iter()]
        self.assertEqual(results, range(1, 24))
        self.assertEqual(len(connections['default'].queries), 4)

    def test_related_fill_cache(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        results = self.rsqs.all()
        self.assertEqual(len(results._result_cache), 0)
        self.assertEqual(len(connections['default'].queries), 0)
        results._fill_cache(0, 10)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 10)
        self.assertEqual(len(connections['default'].queries), 1)
        results._fill_cache(10, 20)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 20)
        self.assertEqual(len(connections['default'].queries), 2)

    def test_related_cache_is_full(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        self.assertEqual(self.rsqs._cache_is_full(), False)
        results = self.rsqs.all()
        fire_the_iterator_and_fill_cache = [result for result in results]
        self.assertEqual(results._cache_is_full(), True)
        self.assertEqual(len(connections['default'].queries), 5)

    def test_quotes_regression(self):
        sqs = self.sqs.auto_query(u"44°48'40''N 20°28'32''E")
        # Should not have empty terms.
        self.assertEqual(sqs.query.build_query(),
                         u"44\xb048'40''N 20\xb028'32''E")
        # Should not cause Solr to 500.
        self.assertEqual(sqs.count(), 0)

        sqs = self.sqs.auto_query('blazing')
        self.assertEqual(sqs.query.build_query(), u'blazing')
        self.assertEqual(sqs.count(), 0)
        sqs = self.sqs.auto_query('blazing saddles')
        self.assertEqual(sqs.query.build_query(), u'blazing saddles')
        self.assertEqual(sqs.count(), 0)
        sqs = self.sqs.auto_query('"blazing saddles')
        self.assertEqual(sqs.query.build_query(), u'\\"blazing saddles')
        self.assertEqual(sqs.count(), 0)
        sqs = self.sqs.auto_query('"blazing saddles"')
        self.assertEqual(sqs.query.build_query(), u'"blazing saddles"')
        self.assertEqual(sqs.count(), 0)
        sqs = self.sqs.auto_query('mel "blazing saddles"')
        self.assertEqual(sqs.query.build_query(), u'mel "blazing saddles"')
        self.assertEqual(sqs.count(), 0)
        sqs = self.sqs.auto_query('mel "blazing \'saddles"')
        self.assertEqual(sqs.query.build_query(), u'mel "blazing \'saddles"')
        self.assertEqual(sqs.count(), 0)
        sqs = self.sqs.auto_query('mel "blazing \'\'saddles"')
        self.assertEqual(sqs.query.build_query(), u'mel "blazing \'\'saddles"')
        self.assertEqual(sqs.count(), 0)
        sqs = self.sqs.auto_query('mel "blazing \'\'saddles"\'')
        self.assertEqual(sqs.query.build_query(),
                         u'mel "blazing \'\'saddles" \'')
        self.assertEqual(sqs.count(), 0)
        sqs = self.sqs.auto_query('mel "blazing \'\'saddles"\'"')
        self.assertEqual(sqs.query.build_query(),
                         u'mel "blazing \'\'saddles" \'\\"')
        self.assertEqual(sqs.count(), 0)
        sqs = self.sqs.auto_query('"blazing saddles" mel')
        self.assertEqual(sqs.query.build_query(), u'"blazing saddles" mel')
        self.assertEqual(sqs.count(), 0)
        sqs = self.sqs.auto_query('"blazing saddles" mel brooks')
        self.assertEqual(sqs.query.build_query(),
                         u'"blazing saddles" mel brooks')
        self.assertEqual(sqs.count(), 0)
        sqs = self.sqs.auto_query('mel "blazing saddles" brooks')
        self.assertEqual(sqs.query.build_query(),
                         u'mel "blazing saddles" brooks')
        self.assertEqual(sqs.count(), 0)
        sqs = self.sqs.auto_query('mel "blazing saddles" "brooks')
        self.assertEqual(sqs.query.build_query(),
                         u'mel "blazing saddles" \\"brooks')
        self.assertEqual(sqs.count(), 0)

    def test_result_class(self):
        # Assert that we're defaulting to ``SearchResult``.
        sqs = self.sqs.all()
        self.assertTrue(isinstance(sqs[0], SearchResult))

        # Custom class.
        sqs = self.sqs.result_class(MockSearchResult).all()
        self.assertTrue(isinstance(sqs[0], MockSearchResult))

        # Reset to default.
        sqs = self.sqs.result_class(None).all()
        self.assertTrue(isinstance(sqs[0], SearchResult))
Beispiel #41
0
    def queryset(self, postdata, exclude=None):
        """
        Build the `self.model` queryset limited to selected filters.
        """

        if self.qs is None:
            #qs = self.model.objects.all().select_related()
            from haystack.query import SearchQuerySet
            qs = SearchQuerySet()
            if self.connection: qs = qs.using(self.connection)
            qs = qs.filter(indexed_model_name__in=[self.model.__name__],
                           **self.global_filters)
        else:
            qs = self.qs

        filters = {}
        filters2 = []

        # Then for each filter
        for option in self.options:
            # If filter is not excluded explicitly (used to get counts
            # for choices).
            if option == exclude: continue

            # If filter contains valid data, check jQuery style encoding of array params
            if option.field_name not in postdata and option.field_name + "[]" not in postdata:
                continue

            # Do filtering

            if option.filter is not None:
                qs_ = option.filter(qs, postdata)

                if isinstance(qs_, dict):
                    filters.update(qs_)
                else:
                    qs = qs_

            else:
                values = postdata.getlist(
                    option.field_name) + postdata.getlist(option.field_name +
                                                          "[]")

                if option.type == "text":
                    # For full-text searching, don't use __in so that the search
                    # backend does its usual query operation.
                    values = " ".join(
                        values
                    )  # should not really be more than one, but in case the parameter is specified multiple times in the query string
                    if self.qs is None:
                        # This is a Haystack search. Handle text a little differently.
                        # Wrap it in an AutoQuery so advanced search options like quoted phrases are used.
                        # Query both text and text_boosted, which has a boost applied at the field level.
                        from haystack.query import SQ
                        from haystack.inputs import AutoQuery
                        values = AutoQuery(values)
                        filters2.append(
                            SQ(text=values) | SQ(text_boosted=values))
                    else:
                        filters[option.orm_field_name] = values

                elif not u'__ALL__' in values:
                    # if __ALL__ value presents in filter values
                    # then do not limit queryset

                    def parse_booleans(x):
                        for y in x:
                            if y in ("true", "on"):
                                yield True
                            elif y == "false":
                                yield False
                            else:
                                yield y

                    values = list(parse_booleans(values))

                    filters['%s__in' % option.orm_field_name] = values

        # apply filters simultaneously so that filters on related objects are applied
        # to the same related object. if they were applied chained (i.e. filter().filter())
        # then they could apply to different objects.
        if len(filters) + len(filters2) > 0:
            qs = qs.filter(*filters2, **filters)

        for name, key, default, func in self.sort_options:
            if postdata.get("sort", "") == key:
                if not func:
                    qs = qs.order_by(key)
                else:
                    qs = func(qs)

        # Django ORM but not Haystack
        if hasattr(qs, 'distinct'):
            return qs.distinct()

        # Haystack but not Django ORM
        else:
            # Revise the SearchQuerySet to iterate over model objects
            # rather than SearchResult objects.
            class SR:
                def __init__(self, qs):
                    self.qs = qs

                def facet(self, field, **kwargs):
                    return self.qs.facet(field, **kwargs)

                def count(self):
                    return len(self.qs)

                def order_by(self, field):
                    return SR(self.qs.order_by(field))

                def __len__(self):
                    return len(self.qs)

                def __getitem__(self, index):  # slices too
                    return SR(self.qs[index])

                def __iter__(self):
                    for item in self.qs:
                        yield item.object

            return SR(qs)
Beispiel #42
0
class LiveSolrMoreLikeThisTestCase(TestCase):
    fixtures = ['bulk_data.json']

    def setUp(self):
        super(LiveSolrMoreLikeThisTestCase, self).setUp()

        # Wipe it clean.
        clear_solr_index()

        self.old_ui = connections['default'].get_unified_index()
        self.ui = UnifiedIndex()
        self.smmi = SolrMockModelSearchIndex()
        self.sammi = SolrAnotherMockModelSearchIndex()
        self.ui.build(indexes=[self.smmi, self.sammi])
        connections['default']._index = self.ui

        self.sqs = SearchQuerySet()

        self.smmi.update()
        self.sammi.update()

    def tearDown(self):
        # Restore.
        connections['default']._index = self.old_ui
        super(LiveSolrMoreLikeThisTestCase, self).tearDown()

    def test_more_like_this(self):
        mlt = self.sqs.more_like_this(MockModel.objects.get(pk=1))
        self.assertEqual(mlt.count(), 22)
        self.assertEqual([result.pk for result in mlt], [
            '14', '6', '10', '22', '4', '5', '3', '12', '2', '19', '18', '13',
            '15', '21', '7', '23', '20', '9', '1', '2', '17', '16'
        ])
        self.assertEqual(len([result.pk for result in mlt]), 22)

        alt_mlt = self.sqs.filter(name='daniel3').more_like_this(
            MockModel.objects.get(pk=3))
        self.assertEqual(alt_mlt.count(), 8)
        self.assertEqual([result.pk for result in alt_mlt],
                         ['17', '16', '19', '23', '22', '13', '1', '2'])
        self.assertEqual(len([result.pk for result in alt_mlt]), 8)

        alt_mlt_with_models = self.sqs.models(MockModel).more_like_this(
            MockModel.objects.get(pk=1))
        self.assertEqual(alt_mlt_with_models.count(), 20)
        self.assertEqual([result.pk for result in alt_mlt_with_models], [
            '14', '6', '10', '22', '4', '5', '3', '12', '2', '19', '18', '13',
            '15', '21', '7', '23', '20', '9', '17', '16'
        ])
        self.assertEqual(len([result.pk for result in alt_mlt_with_models]),
                         20)

        if hasattr(MockModel.objects, 'defer'):
            # Make sure MLT works with deferred bits.
            mi = MockModel.objects.defer('foo').get(pk=1)
            self.assertEqual(mi._deferred, True)
            deferred = self.sqs.models(MockModel).more_like_this(mi)
            self.assertEqual(deferred.count(), 0)
            self.assertEqual([result.pk for result in deferred], [])
            self.assertEqual(len([result.pk for result in deferred]), 0)

        # Ensure that swapping the ``result_class`` works.
        self.assertTrue(
            isinstance(
                self.sqs.result_class(MockSearchResult).more_like_this(
                    MockModel.objects.get(pk=1))[0], MockSearchResult))
Beispiel #43
0
    def search(self, order_by='newest'):
        self.clean()
        sqs = SearchQuerySet()
        if self.is_valid():
            query = self.cleaned_data['q']
        else:
            query = ''
        
        if not query:
            return sqs.none()
        
        if not order_by:
            order_by = 'newest'

        sqs = sqs.filter(status=True)
        user = self.user

        is_an_admin = user.profile.is_superuser

        # making a special case for corp memb because it needs to utilize two settings
        # (anonymoussearchcorporatemembers and membersearchcorporatemembers)
        if CorpMemb and self.cleaned_data['models'] == ["%s.%s" % (CorpMemb._meta.app_label,
                                                                   CorpMemb._meta.model_name)]:
            filter_and, filter_or = CorpMemb.get_search_filter(user)
            q_obj = None
            if filter_and:
                q_obj = Q(**filter_and)
            if filter_or:
                q_obj_or = reduce(operator.or_, [Q(**{key: value}) for key, value in filter_or.items()])
                if q_obj:
                    q_obj = reduce(operator.and_, [q_obj, q_obj_or])
                else:
                    q_obj = q_obj_or
            if q_obj:
                sqs = sqs.filter(q_obj)

            if query:
                sqs = sqs.auto_query(sqs.query.clean(query))
        else:

            if query:
                sqs = sqs.auto_query(sqs.query.clean(query))
                if user:
                    if not is_an_admin:
                        if not user.is_anonymous:
                        # if b/w admin and anon

                            # (status+status_detail+(anon OR user)) OR (who_can_view__exact)
                            anon_query = Q(**{'allow_anonymous_view':True,})
                            user_query = Q(**{'allow_user_view':True,})
                            sec1_query = Q(**{
                                'status_detail':'active',
                            })
                            sec2_query = Q(**{
                                'owner__exact':user.username
                            })
                            query = reduce(operator.or_, [anon_query, user_query])
                            query = reduce(operator.and_, [sec1_query, query])
                            query = reduce(operator.or_, [query, sec2_query])

                            sqs = sqs.filter(query)
                        else:
                        # if anonymous
                            sqs = sqs.filter(status_detail='active')
                            sqs = sqs.filter(allow_anonymous_view=True)
                else:
                    # if anonymous
                    sqs = sqs.filter(status_detail='active')
                    sqs = sqs.filter(allow_anonymous_view=True)
            else:
                if user:
                    if is_an_admin:
                        sqs = sqs.all()
                    else:
                        if not user.is_anonymous:
                            # (status+status_detail+anon OR who_can_view__exact)
                            sec1_query = Q(**{
                                'status_detail':'active',
                                'allow_anonymous_view':True,
                            })
                            sec2_query = Q(**{
                                'owner__exact':user.username
                            })
                            query = reduce(operator.or_, [sec1_query, sec2_query])
                            sqs = sqs.filter(query)
                        else:
                            # if anonymous
                            sqs = sqs.filter(status_detail='active')
                            sqs = sqs.filter(allow_anonymous_view=True)
                else:
                    # if anonymous
                    sqs = sqs.filter(status_detail='active')
                    sqs = sqs.filter(allow_anonymous_view=True)

            # for solr,
            # order_by can only called once so we have to do it here
            if order_by == 'newest':
                # changed order_by from create_dt to order because the order field
                # is a common field in search indexes and used by other modules(news)
                sqs = sqs.order_by('-order')
            else:
                sqs = sqs.order_by('order')

        if self.load_all:
            sqs = sqs.load_all()

        return sqs
Beispiel #44
0
 def _search_in_dictionary_language(
     self, text: str, query_set: SearchQuerySet
 ) -> SearchQuerySet:
     return query_set.filter(head_simplified__startswith=to_search_form(text))
class LiveWhooshRamStorageTestCase(TestCase):
    def setUp(self):
        super(LiveWhooshRamStorageTestCase, self).setUp()

        # Stow.
        self.old_whoosh_storage = settings.HAYSTACK_CONNECTIONS['whoosh'].get(
            'STORAGE', 'file')
        settings.HAYSTACK_CONNECTIONS['whoosh']['STORAGE'] = 'ram'

        self.old_ui = connections['whoosh'].get_unified_index()
        self.ui = UnifiedIndex()
        self.wrtsi = WhooshRoundTripSearchIndex()
        self.ui.build(indexes=[self.wrtsi])
        self.sb = connections['whoosh'].get_backend()
        connections['whoosh']._index = self.ui

        # Stow.
        import haystack

        self.sb.setup()
        self.raw_whoosh = self.sb.index
        self.parser = QueryParser(self.sb.content_field_name,
                                  schema=self.sb.schema)

        self.sqs = SearchQuerySet('whoosh')

        # Wipe it clean.
        self.sqs.query.backend.clear()

        # Fake indexing.
        mock = MockModel()
        mock.id = 1
        self.sb.update(self.wrtsi, [mock])

    def tearDown(self):
        self.sqs.query.backend.clear()

        settings.HAYSTACK_CONNECTIONS['whoosh'][
            'STORAGE'] = self.old_whoosh_storage
        connections['whoosh']._index = self.old_ui
        super(LiveWhooshRamStorageTestCase, self).tearDown()

    def test_ram_storage(self):
        results = self.sqs.filter(id='core.mockmodel.1')

        # Sanity check.
        self.assertEqual(results.count(), 1)

        # Check the individual fields.
        result = results[0]
        self.assertEqual(result.id, 'core.mockmodel.1')
        self.assertEqual(result.text, 'This is some example text.')
        self.assertEqual(result.name, 'Mister Pants')
        self.assertEqual(result.is_active, True)
        self.assertEqual(result.post_count, 25)
        self.assertEqual(result.average_rating, 3.6)
        self.assertEqual(result.pub_date, datetime(2009, 11, 21, 0, 0))
        self.assertEqual(result.created, datetime(2009, 11, 21, 21, 31, 00))
        self.assertEqual(result.tags,
                         ['staff', 'outdoor', 'activist', 'scientist'])
        self.assertEqual(result.sites, [u'3', u'5', u'1'])
        self.assertEqual(result.empty_list, [])
Beispiel #46
0
    def search(self):
        # First, store the SearchQuerySet received from other processing.
        if not self.is_valid():
            print("Here")
            return self.no_query_found()
        print("Search Valid")

        if self.cleaned_data["q"] == "":
            # sqs = SearchQuerySet().exclude(no_such_field="x")
            # sqs = SearchQuerySet().filter(content="soccer")
            sqs = SearchQuerySet()
            print(sqs.count())
            # sqs = sqs.filter(content="soccer")
            print("q = ''")
        else:
            print("q = something")
            sqs = super(grasaSearchForm, self).search()
            print(sqs.count())

        selectedActivities = self.cleaned_data["activities"]
        for activity in activityList:
            for selectedActivity in selectedActivities:
                print(selectedActivity)
                if activity[0] == selectedActivity:
                    sqs = sqs.filter(content=activity[0])

        selectedTransportations = self.cleaned_data["transportations"]
        for transportation in transportationList:
            for selectedTransportation in selectedTransportations:
                if transportation[0] == selectedTransportation:
                    print('inside transport filter')
                    print(transportation[0])
                    print(selectedTransportation)
                    sqs = sqs.filter(content=transportation[0])

        selectedGrades = self.cleaned_data["grades"]
        for grade in gradesList:
            for selectedGrade in selectedGrades:
                if grade[0] == selectedGrade:
                    sqs = sqs.filter(content=grade[0])

        selectedGenders = self.cleaned_data["genders"]
        for gender in genderList:
            for selectedGender in selectedGenders:
                if gender[0] == selectedGender:
                    sqs = sqs.filter(content=gender[0])

        # Needs changes
        selectedFees = self.cleaned_data["fees"]
        for selectedFee in selectedFees:
            # These need to be specially written since they aren't stored as a range in the DB
            if "Free" == selectedFee:
                print("Free selected")
                sqs = sqs.filter(fees=0.00)
            if "$1-$25" == selectedFee:
                print("$1-$25 selected")
                sqs = sqs.filter(fees__gte=0.01)
                sqs = sqs.filter(fees__lte=25.99)
            if "$26-$50" == selectedFee:
                print("$26-$50 selected")
                print(sqs.count())
                sqs = sqs.filter(fees__gte=26.00)
                sqs = sqs.filter(fees__lte=50.99)
                print(sqs.count())
            if "$51-$75" == selectedFee:
                print("$51-$75 selected")
                sqs = sqs.filter(fees__gte=51.00)
                sqs = sqs.filter(fees__lte=75.99)
            if "$75+" == selectedFee:
                sqs = sqs.filter(fees__gte=75.00)

        selectedTimings = self.cleaned_data["timings"]
        for timing in timingList:
            for selectedTiming in selectedTimings:
                if timing[0] == selectedTiming:
                    sqs = sqs.filter(content=timing[0])
        print(sqs.count())
        return sqs
Beispiel #47
0
    def list(self, request, *args, **kwargs):
        # If the incoming language is not specified, go with the default.
        self.lang_code = request.QUERY_PARAMS.get('language', LANGUAGES[0])
        if self.lang_code not in LANGUAGES:
            raise ParseError(
                "Invalid language supplied. Supported languages: %s" %
                ','.join(LANGUAGES))

        context = {}

        specs = {
            'only_fields': self.request.QUERY_PARAMS.get('only', None),
            'include_fields': self.request.QUERY_PARAMS.get('include', None)
        }
        for key in specs.keys():
            if specs[key]:
                setattr(self, key, {})
                fields = [
                    x.strip().split('.') for x in specs[key].split(',') if x
                ]
                for f in fields:
                    try:
                        getattr(self, key).setdefault(f[0], []).append(f[1])
                    except IndexError:
                        logger.warning(
                            "Field '%s' given in unsupported non-dot-format: '%s'"
                            % (key, specs[key]))
            else:
                setattr(self, key, None)

        input_val = request.QUERY_PARAMS.get('input', '').strip()
        q_val = request.QUERY_PARAMS.get('q', '').strip()
        if not input_val and not q_val:
            raise ParseError(
                "Supply search terms with 'q=' or autocomplete entry with 'input='"
            )
        if input_val and q_val:
            raise ParseError("Supply either 'q' or 'input', not both")

        old_language = translation.get_language()[:2]
        translation.activate(self.lang_code)

        queryset = SearchQuerySet()

        if hasattr(request, 'accepted_media_type') and re.match(
                KML_REGEXP, request.accepted_media_type):
            queryset = queryset.models(Unit)
            self.only_fields['unit'].extend(['street_address', 'www_url'])

        if input_val:
            queryset = (queryset.filter(autosuggest=input_val).filter_or(
                autosuggest_extra_searchwords=input_val).filter_or(
                    autosuggest_exact__exact=input_val))
        else:
            queryset = (queryset.filter(text=AutoQuery(q_val)).filter_or(
                extra_searchwords=q_val).filter_or(address=q_val))
        if 'municipality' in request.QUERY_PARAMS:
            val = request.QUERY_PARAMS['municipality'].lower().strip()
            if len(val) > 0:
                municipalities = val.split(',')
                muni_q_objects = [
                    SQ(municipality=m.strip()) for m in municipalities
                ]
                muni_q = muni_q_objects.pop()
                for q in muni_q_objects:
                    muni_q |= q
                queryset = queryset.filter(
                    SQ(muni_q | SQ(django_ct='services.service')
                       | SQ(django_ct='munigeo.address')))

        service = request.QUERY_PARAMS.get('service')
        if service:
            services = service.split(',')
            queryset = queryset.filter(django_ct='services.unit').filter(
                services__in=services)

        models = set()
        types = request.QUERY_PARAMS.get('type', '').split(',')
        for t in types:
            if t == 'service':
                models.add(Service)
            elif t == 'unit':
                models.add(Unit)
            elif t == 'address':
                models.add(Address)
        if len(models) > 0:
            queryset = queryset.models(*list(models))

        only = getattr(self, 'only_fields') or {}
        include = getattr(self, 'include_fields') or {}
        Unit.search_objects.only_fields = only.get('unit')
        Unit.search_objects.include_fields = include.get('unit')

        self.object_list = queryset.load_all()

        # Switch between paginated or standard style responses
        page = self.paginate_queryset(self.object_list)
        serializer = self.get_serializer(page, many=True)
        resp = self.get_paginated_response(serializer.data)

        translation.activate(old_language)

        return resp
Beispiel #48
0
    def regulation_results_page(self, request):
        all_regs = Part.objects.order_by('part_number')
        regs = validate_regs_list(request)
        order = validate_order(request)
        search_query = request.GET.get('q', '').strip()
        payload = {
            'search_query': search_query,
            'results': [],
            'total_results': 0,
            'regs': regs,
            'all_regs': [],
        }
        if not search_query or len(urllib.parse.unquote(search_query)) == 1:
            self.results = payload
            return TemplateResponse(request, self.get_template(request),
                                    self.get_context(request))
        sqs = SearchQuerySet().filter(content=search_query)
        payload.update({
            'all_regs': [{
                'short_name':
                reg.short_name,
                'id':
                reg.part_number,
                'num_results':
                sqs.filter(
                    part=reg.part_number).models(SectionParagraph).count(),
                'selected':
                reg.part_number in regs
            } for reg in all_regs]
        })
        payload.update({
            'total_count':
            sum([reg['num_results'] for reg in payload['all_regs']])
        })
        if len(regs) == 1:
            sqs = sqs.filter(part=regs[0])
        elif regs:
            sqs = sqs.filter(part__in=regs)
        if order == 'regulation':
            sqs = sqs.order_by('part', 'section_order')
        sqs = sqs.highlight(pre_tags=['<strong>'],
                            post_tags=['</strong>']).models(SectionParagraph)
        for hit in sqs:
            try:
                snippet = Markup(" ".join(hit.highlighted))
            except TypeError as e:
                logger.warning(
                    "Query string {} produced a TypeError: {}".format(
                        search_query, e))
                continue

            short_name = all_regs.get(part_number=hit.part).short_name
            hit_payload = {
                'id':
                hit.paragraph_id,
                'part':
                hit.part,
                'reg':
                short_name,
                'label':
                hit.title,
                'snippet':
                snippet,
                'url':
                "{}{}/{}/#{}".format(self.parent().url, hit.part,
                                     hit.section_label, hit.paragraph_id),
            }
            payload['results'].append(hit_payload)

        payload.update({'current_count': sqs.count()})
        self.results = payload
        context = self.get_context(request)
        num_results = validate_num_results(request)
        paginator = Paginator(payload['results'], num_results)
        page_number = validate_page_number(request, paginator)
        paginated_page = paginator.page(page_number)
        context.update({
            'current_count':
            payload['current_count'],
            'total_count':
            payload['total_count'],
            'paginator':
            paginator,
            'current_page':
            page_number,
            'num_results':
            num_results,
            'order':
            order,
            'results':
            paginated_page,
            'show_filters':
            any(reg['selected'] is True for reg in payload['all_regs'])
        })
        return TemplateResponse(request, self.get_template(request), context)
Beispiel #49
0
class SearchQuerySetTestCase(TestCase):
    fixtures = ['bulk_data.json']

    def setUp(self):
        super(SearchQuerySetTestCase, self).setUp()

        # Stow.
        self.old_unified_index = connections['default']._index
        self.ui = UnifiedIndex()
        self.bmmsi = BasicMockModelSearchIndex()
        self.cpkmmsi = CharPKMockModelSearchIndex()
        self.ui.build(indexes=[self.bmmsi, self.cpkmmsi])
        connections['default']._index = self.ui

        # Update the "index".
        backend = connections['default'].get_backend()
        backend.clear()
        backend.update(self.bmmsi, MockModel.objects.all())

        self.msqs = SearchQuerySet()

        # Stow.
        reset_search_queries()

    def tearDown(self):
        # Restore.
        connections['default']._index = self.old_unified_index
        super(SearchQuerySetTestCase, self).tearDown()

    def test_len(self):
        self.assertEqual(len(self.msqs), 23)

    def test_repr(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        self.assertEqual(
            repr(self.msqs).replace("u'", "'"),
            "[<SearchResult: core.mockmodel (pk='1')>, <SearchResult: core.mockmodel (pk='2')>, <SearchResult: core.mockmodel (pk='3')>, <SearchResult: core.mockmodel (pk='4')>, <SearchResult: core.mockmodel (pk='5')>, <SearchResult: core.mockmodel (pk='6')>, <SearchResult: core.mockmodel (pk='7')>, <SearchResult: core.mockmodel (pk='8')>, <SearchResult: core.mockmodel (pk='9')>, <SearchResult: core.mockmodel (pk='10')>, <SearchResult: core.mockmodel (pk='11')>, <SearchResult: core.mockmodel (pk='12')>, <SearchResult: core.mockmodel (pk='13')>, <SearchResult: core.mockmodel (pk='14')>, <SearchResult: core.mockmodel (pk='15')>, <SearchResult: core.mockmodel (pk='16')>, <SearchResult: core.mockmodel (pk='17')>, <SearchResult: core.mockmodel (pk='18')>, <SearchResult: core.mockmodel (pk='19')>, '...(remaining elements truncated)...']"
        )
        self.assertEqual(len(connections['default'].queries), 1)

    def test_iter(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        msqs = self.msqs.all()
        results = [int(res.pk) for res in msqs]
        self.assertEqual(results, [res.pk for res in MOCK_SEARCH_RESULTS[:23]])
        self.assertEqual(len(connections['default'].queries), 3)

    def test_slice(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        results = self.msqs.all()
        self.assertEqual([int(res.pk) for res in results[1:11]],
                         [res.pk for res in MOCK_SEARCH_RESULTS[1:11]])
        self.assertEqual(len(connections['default'].queries), 1)

        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        results = self.msqs.all()
        self.assertEqual(int(results[22].pk), MOCK_SEARCH_RESULTS[22].pk)
        self.assertEqual(len(connections['default'].queries), 1)

    def test_manual_iter(self):
        results = self.msqs.all()

        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)

        check = [result.pk for result in results._manual_iter()]
        self.assertEqual(check, [
            u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'10', u'11',
            u'12', u'13', u'14', u'15', u'16', u'17', u'18', u'19', u'20',
            u'21', u'22', u'23'
        ])

        self.assertEqual(len(connections['default'].queries), 3)

        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)

        # Test to ensure we properly fill the cache, even if we get fewer
        # results back (not a handled model) than the hit count indicates.
        # This will hang indefinitely if broken.
        old_ui = self.ui
        self.ui.build(indexes=[self.cpkmmsi])
        connections['default']._index = self.ui
        self.cpkmmsi.update()

        results = self.msqs.all()
        loaded = [result.pk for result in results._manual_iter()]
        self.assertEqual(loaded, [u'sometext', u'1234'])
        self.assertEqual(len(connections['default'].queries), 1)

        connections['default']._index = old_ui

    def test_fill_cache(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        results = self.msqs.all()
        self.assertEqual(len(results._result_cache), 0)
        self.assertEqual(len(connections['default'].queries), 0)
        results._fill_cache(0, 10)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 10)
        self.assertEqual(len(connections['default'].queries), 1)
        results._fill_cache(10, 20)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 20)
        self.assertEqual(len(connections['default'].queries), 2)

        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)

        # Test to ensure we properly fill the cache, even if we get fewer
        # results back (not a handled model) than the hit count indicates.
        sqs = SearchQuerySet().all()
        sqs.query.backend = MixedMockSearchBackend('default')
        results = sqs
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 0)
        self.assertEqual([
            int(result.pk)
            for result in results._result_cache if result is not None
        ], [])
        self.assertEqual(len(connections['default'].queries), 0)
        results._fill_cache(0, 10)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 9)
        self.assertEqual([
            int(result.pk)
            for result in results._result_cache if result is not None
        ], [1, 2, 3, 4, 5, 6, 7, 8, 10])
        self.assertEqual(len(connections['default'].queries), 2)
        results._fill_cache(10, 20)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 17)
        self.assertEqual([
            int(result.pk)
            for result in results._result_cache if result is not None
        ], [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 17, 18, 19, 20])
        self.assertEqual(len(connections['default'].queries), 4)
        results._fill_cache(20, 30)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 20)
        self.assertEqual([
            int(result.pk)
            for result in results._result_cache if result is not None
        ], [
            1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22,
            23
        ])
        self.assertEqual(len(connections['default'].queries), 6)

    def test_cache_is_full(self):
        reset_search_queries()
        self.assertEqual(len(connections['default'].queries), 0)
        self.assertEqual(self.msqs._cache_is_full(), False)
        results = self.msqs.all()
        fire_the_iterator_and_fill_cache = [result for result in results]
        self.assertEqual(results._cache_is_full(), True)
        self.assertEqual(len(connections['default'].queries), 3)

    def test_all(self):
        sqs = self.msqs.all()
        self.assertTrue(isinstance(sqs, SearchQuerySet))

    def test_filter(self):
        sqs = self.msqs.filter(content='foo')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 1)

    def test_exclude(self):
        sqs = self.msqs.exclude(content='foo')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 1)

    def test_order_by(self):
        sqs = self.msqs.order_by('foo')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertTrue('foo' in sqs.query.order_by)

    def test_models(self):
        # Stow.
        old_unified_index = connections['default']._index
        ui = UnifiedIndex()
        bmmsi = BasicMockModelSearchIndex()
        bammsi = BasicAnotherMockModelSearchIndex()
        ui.build(indexes=[bmmsi, bammsi])
        connections['default']._index = ui

        msqs = SearchQuerySet()

        sqs = msqs.all()
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.models), 0)

        sqs = msqs.models(MockModel)
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.models), 1)

        sqs = msqs.models(MockModel, AnotherMockModel)
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.models), 2)

        # This will produce a warning.
        ui.build(indexes=[bmmsi])
        sqs = msqs.models(AnotherMockModel)
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.models), 1)

    def test_result_class(self):
        sqs = self.msqs.all()
        self.assertTrue(issubclass(sqs.query.result_class, SearchResult))

        # Custom class.
        class IttyBittyResult(object):
            pass

        sqs = self.msqs.result_class(IttyBittyResult)
        self.assertTrue(issubclass(sqs.query.result_class, IttyBittyResult))

        # Reset to default.
        sqs = self.msqs.result_class(None)
        self.assertTrue(issubclass(sqs.query.result_class, SearchResult))

    def test_boost(self):
        sqs = self.msqs.boost('foo', 10)
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.boost.keys()), 1)

    def test_highlight(self):
        sqs = self.msqs.highlight()
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(sqs.query.highlight, True)

    def test_spelling(self):
        # Test the case where spelling support is disabled.
        sqs = self.msqs.filter(content='Indx')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(sqs.spelling_suggestion(), None)
        self.assertEqual(sqs.spelling_suggestion('indexy'), None)

    def test_raw_search(self):
        self.assertEqual(len(self.msqs.raw_search('foo')), 23)
        self.assertEqual(
            len(
                self.msqs.raw_search(
                    '(content__exact:hello AND content__exact:world)')), 23)

    def test_load_all(self):
        # Models with character primary keys.
        sqs = SearchQuerySet()
        sqs.query.backend = CharPKMockSearchBackend('charpk')
        results = sqs.load_all().all()
        self.assertEqual(len(results._result_cache), 0)
        results._fill_cache(0, 2)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 2)

        # If nothing is handled, you get nothing.
        old_ui = connections['default']._index
        ui = UnifiedIndex()
        ui.build(indexes=[])
        connections['default']._index = ui

        sqs = self.msqs.load_all()
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs), 0)

        connections['default']._index = old_ui

        # For full tests, see the solr_backend.

    def test_load_all_read_queryset(self):
        # Stow.
        old_ui = connections['default']._index
        ui = UnifiedIndex()
        gafmmsi = GhettoAFifthMockModelSearchIndex()
        ui.build(indexes=[gafmmsi])
        connections['default']._index = ui
        gafmmsi.update()

        sqs = SearchQuerySet()
        results = sqs.load_all().all()
        results.query.backend = ReadQuerySetMockSearchBackend('default')
        results._fill_cache(0, 2)

        # The deleted result isn't returned
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 1)

        # Register a SearchIndex with a read_queryset that returns deleted items
        rqstsi = TextReadQuerySetTestSearchIndex()
        ui.build(indexes=[rqstsi])
        rqstsi.update()

        sqs = SearchQuerySet()
        results = sqs.load_all().all()
        results.query.backend = ReadQuerySetMockSearchBackend('default')
        results._fill_cache(0, 2)

        # Both the deleted and not deleted items are returned
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 2)

        # Restore.
        connections['default']._index = old_ui

    def test_auto_query(self):
        sqs = self.msqs.auto_query('test search -stuff')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(repr(sqs.query.query_filter),
                         '<SQ: AND content__contains=test search -stuff>')

        sqs = self.msqs.auto_query('test "my thing" search -stuff')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(
            repr(sqs.query.query_filter),
            '<SQ: AND content__contains=test "my thing" search -stuff>')

        sqs = self.msqs.auto_query(
            'test "my thing" search \'moar quotes\' -stuff')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(
            repr(sqs.query.query_filter),
            '<SQ: AND content__contains=test "my thing" search \'moar quotes\' -stuff>'
        )

        sqs = self.msqs.auto_query(
            'test "my thing" search \'moar quotes\' "foo -stuff')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(
            repr(sqs.query.query_filter),
            '<SQ: AND content__contains=test "my thing" search \'moar quotes\' "foo -stuff>'
        )

        sqs = self.msqs.auto_query('test - stuff')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(repr(sqs.query.query_filter),
                         "<SQ: AND content__contains=test - stuff>")

        # Ensure bits in exact matches get escaped properly as well.
        sqs = self.msqs.auto_query('"pants:rule"')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(repr(sqs.query.query_filter),
                         '<SQ: AND content__contains="pants:rule">')

        # Now with a different fieldname
        sqs = self.msqs.auto_query('test search -stuff', fieldname='title')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(repr(sqs.query.query_filter),
                         "<SQ: AND title__contains=test search -stuff>")

        sqs = self.msqs.auto_query('test "my thing" search -stuff',
                                   fieldname='title')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(
            repr(sqs.query.query_filter),
            '<SQ: AND title__contains=test "my thing" search -stuff>')

    def test_count(self):
        self.assertEqual(self.msqs.count(), 23)

    def test_facet_counts(self):
        self.assertEqual(self.msqs.facet_counts(), {})

    def test_best_match(self):
        self.assertTrue(isinstance(self.msqs.best_match(), SearchResult))

    def test_latest(self):
        self.assertTrue(isinstance(self.msqs.latest('pub_date'), SearchResult))

    def test_more_like_this(self):
        mock = MockModel()
        mock.id = 1

        self.assertEqual(len(self.msqs.more_like_this(mock)), 23)

    def test_facets(self):
        sqs = self.msqs.facet('foo')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.facets), 1)

        sqs2 = self.msqs.facet('foo').facet('bar')
        self.assertTrue(isinstance(sqs2, SearchQuerySet))
        self.assertEqual(len(sqs2.query.facets), 2)

    def test_date_facets(self):
        try:
            sqs = self.msqs.date_facet('foo',
                                       start_date=datetime.date(2008, 2, 25),
                                       end_date=datetime.date(2009, 2, 25),
                                       gap_by='smarblaph')
            self.fail()
        except FacetingError as e:
            self.assertEqual(
                str(e),
                "The gap_by ('smarblaph') must be one of the following: year, month, day, hour, minute, second."
            )

        sqs = self.msqs.date_facet('foo',
                                   start_date=datetime.date(2008, 2, 25),
                                   end_date=datetime.date(2009, 2, 25),
                                   gap_by='month')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.date_facets), 1)

        sqs2 = self.msqs.date_facet('foo',
                                    start_date=datetime.date(2008, 2, 25),
                                    end_date=datetime.date(2009, 2, 25),
                                    gap_by='month').date_facet(
                                        'bar',
                                        start_date=datetime.date(2007, 2, 25),
                                        end_date=datetime.date(2009, 2, 25),
                                        gap_by='year')
        self.assertTrue(isinstance(sqs2, SearchQuerySet))
        self.assertEqual(len(sqs2.query.date_facets), 2)

    def test_query_facets(self):
        sqs = self.msqs.query_facet('foo', '[bar TO *]')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_facets), 1)

        sqs2 = self.msqs.query_facet('foo', '[bar TO *]').query_facet(
            'bar', '[100 TO 499]')
        self.assertTrue(isinstance(sqs2, SearchQuerySet))
        self.assertEqual(len(sqs2.query.query_facets), 2)

        # Test multiple query facets on a single field
        sqs3 = self.msqs.query_facet('foo', '[bar TO *]').query_facet(
            'bar', '[100 TO 499]').query_facet('foo', '[1000 TO 1499]')
        self.assertTrue(isinstance(sqs3, SearchQuerySet))
        self.assertEqual(len(sqs3.query.query_facets), 3)

    def test_stats(self):
        sqs = self.msqs.stats_facet('foo', 'bar')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.stats), 1)

        sqs2 = self.msqs.stats_facet('foo', 'bar').stats_facet('foo', 'baz')
        self.assertTrue(isinstance(sqs2, SearchQuerySet))
        self.assertEqual(len(sqs2.query.stats), 1)

        sqs3 = self.msqs.stats_facet('foo', 'bar').stats_facet('moof', 'baz')
        self.assertTrue(isinstance(sqs3, SearchQuerySet))
        self.assertEqual(len(sqs3.query.stats), 2)

    def test_narrow(self):
        sqs = self.msqs.narrow('foo:moof')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.narrow_queries), 1)

    def test_clone(self):
        results = self.msqs.filter(foo='bar', foo__lt='10')

        clone = results._clone()
        self.assertTrue(isinstance(clone, SearchQuerySet))
        self.assertEqual(str(clone.query), str(results.query))
        self.assertEqual(clone._result_cache, [])
        self.assertEqual(clone._result_count, None)
        self.assertEqual(clone._cache_full, False)
        self.assertEqual(clone._using, results._using)

    def test_using(self):
        sqs = SearchQuerySet(using='default')
        self.assertNotEqual(sqs.query, None)
        self.assertEqual(sqs.query._using, 'default')

    def test_chaining(self):
        sqs = self.msqs.filter(content='foo')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 1)

        # A second instance should inherit none of the changes from above.
        sqs = self.msqs.filter(content='bar')
        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 1)

    def test_none(self):
        sqs = self.msqs.none()
        self.assertTrue(isinstance(sqs, EmptySearchQuerySet))
        self.assertEqual(len(sqs), 0)

    def test___and__(self):
        sqs1 = self.msqs.filter(content='foo')
        sqs2 = self.msqs.filter(content='bar')
        sqs = sqs1 & sqs2

        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 2)

    def test___or__(self):
        sqs1 = self.msqs.filter(content='foo')
        sqs2 = self.msqs.filter(content='bar')
        sqs = sqs1 | sqs2

        self.assertTrue(isinstance(sqs, SearchQuerySet))
        self.assertEqual(len(sqs.query.query_filter), 2)

    def test_and_or(self):
        """
        Combining AND queries with OR should give
            AND(OR(a, b), OR(c, d))
        """
        sqs1 = self.msqs.filter(content='foo').filter(content='oof')
        sqs2 = self.msqs.filter(content='bar').filter(content='rab')
        sqs = sqs1 | sqs2

        self.assertEqual(sqs.query.query_filter.connector, 'OR')
        self.assertEqual(repr(sqs.query.query_filter.children[0]),
                         repr(sqs1.query.query_filter))
        self.assertEqual(repr(sqs.query.query_filter.children[1]),
                         repr(sqs2.query.query_filter))

    def test_or_and(self):
        """
        Combining OR queries with AND should give
            OR(AND(a, b), AND(c, d))
        """
        sqs1 = self.msqs.filter(content='foo').filter_or(content='oof')
        sqs2 = self.msqs.filter(content='bar').filter_or(content='rab')
        sqs = sqs1 & sqs2

        self.assertEqual(sqs.query.query_filter.connector, 'AND')
        self.assertEqual(repr(sqs.query.query_filter.children[0]),
                         repr(sqs1.query.query_filter))
        self.assertEqual(repr(sqs.query.query_filter.children[1]),
                         repr(sqs2.query.query_filter))
Beispiel #50
0
class LiveWhooshSearchQuerySetTestCase(WhooshTestCase):
    def setUp(self):
        super(LiveWhooshSearchQuerySetTestCase, self).setUp()

        # Stow.
        self.old_ui = connections['whoosh'].get_unified_index()
        self.ui = UnifiedIndex()
        self.wmmi = WhooshMockSearchIndex()
        self.ui.build(indexes=[self.wmmi])
        self.sb = connections['whoosh'].get_backend()
        connections['whoosh']._index = self.ui

        self.sb.setup()
        self.raw_whoosh = self.sb.index
        self.parser = QueryParser(self.sb.content_field_name, schema=self.sb.schema)
        self.sb.delete_index()

        self.sample_objs = []

        for i in range(1, 4):
            mock = MockModel()
            mock.id = i
            mock.author = 'daniel%s' % i
            mock.pub_date = date(2009, 2, 25) - timedelta(days=i)
            self.sample_objs.append(mock)

        self.sq = connections['whoosh'].get_query()
        self.sqs = SearchQuerySet('whoosh')

    def tearDown(self):
        connections['whoosh']._index = self.old_ui
        super(LiveWhooshSearchQuerySetTestCase, self).tearDown()

    def test_various_searchquerysets(self):
        self.sb.update(self.wmmi, self.sample_objs)

        sqs = self.sqs.filter(content='Index')
        self.assertEqual(sqs.query.build_query(), u'(Index)')
        self.assertEqual(len(sqs), 3)

        sqs = self.sqs.auto_query('Indexed!')
        self.assertEqual(sqs.query.build_query(), u"('Indexed!')")
        self.assertEqual(len(sqs), 3)

        sqs = self.sqs.auto_query('Indexed!').filter(pub_date__lte=date(2009, 8, 31))
        self.assertEqual(sqs.query.build_query(), u"(('Indexed!') AND pub_date:([to 20090831000000]))")
        self.assertEqual(len(sqs), 3)

        sqs = self.sqs.auto_query('Indexed!').filter(pub_date__lte=date(2009, 2, 23))
        self.assertEqual(sqs.query.build_query(), u"(('Indexed!') AND pub_date:([to 20090223000000]))")
        self.assertEqual(len(sqs), 2)

        sqs = self.sqs.auto_query('Indexed!').filter(pub_date__lte=date(2009, 2, 25)).filter(django_id__in=[1, 2]).exclude(name='daniel1')
        self.assertEqual(sqs.query.build_query(), u'((\'Indexed!\') AND pub_date:([to 20090225000000]) AND django_id:(1 OR 2) AND NOT (name:(daniel1)))')
        self.assertEqual(len(sqs), 1)

        sqs = self.sqs.auto_query('re-inker')
        self.assertEqual(sqs.query.build_query(), u"('re-inker')")
        self.assertEqual(len(sqs), 0)

        sqs = self.sqs.auto_query('0.7 wire')
        self.assertEqual(sqs.query.build_query(), u"('0.7' wire)")
        self.assertEqual(len(sqs), 0)

        sqs = self.sqs.auto_query("daler-rowney pearlescent 'bell bronze'")
        self.assertEqual(sqs.query.build_query(), u"('daler-rowney' pearlescent 'bell bronze')")
        self.assertEqual(len(sqs), 0)

        sqs = self.sqs.models(MockModel)
        self.assertEqual(sqs.query.build_query(), u'*')
        self.assertEqual(len(sqs), 3)

    def test_all_regression(self):
        sqs = SearchQuerySet('whoosh')
        self.assertEqual([result.pk for result in sqs], [])

        self.sb.update(self.wmmi, self.sample_objs)
        self.assertTrue(self.sb.index.doc_count() > 0)

        sqs = SearchQuerySet('whoosh')
        self.assertEqual(len(sqs), 3)
        self.assertEqual(sorted([result.pk for result in sqs]), [u'1', u'2', u'3'])

        try:
            sqs = repr(SearchQuerySet('whoosh'))
        except:
            self.fail()

    def test_regression_space_query(self):
        self.sb.update(self.wmmi, self.sample_objs)
        self.assertTrue(self.sb.index.doc_count() > 0)

        sqs = SearchQuerySet('whoosh').auto_query(" ")
        self.assertEqual(len(sqs), 3)
        sqs = SearchQuerySet('whoosh').filter(content=" ")
        self.assertEqual(len(sqs), 0)

    def test_iter(self):
        self.sb.update(self.wmmi, self.sample_objs)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        sqs = self.sqs.auto_query('Indexed!')
        results = [int(result.pk) for result in sqs]
        self.assertEqual(sorted(results), [1, 2, 3])
        self.assertEqual(len(connections['whoosh'].queries), 1)

    def test_slice(self):
        self.sb.update(self.wmmi, self.sample_objs)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        results = self.sqs.auto_query('Indexed!')
        self.assertEqual(sorted([int(result.pk) for result in results[1:3]]), [1, 2])
        self.assertEqual(len(connections['whoosh'].queries), 1)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        results = self.sqs.auto_query('Indexed!')
        self.assertEqual(int(results[0].pk), 1)
        self.assertEqual(len(connections['whoosh'].queries), 1)

    def test_values_slicing(self):
        self.sb.update(self.wmmi, self.sample_objs)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)

        # TODO: this would be a good candidate for refactoring into a TestCase subclass shared across backends

        # The values will come back as strings because Hasytack doesn't assume PKs are integers.
        # We'll prepare this set once since we're going to query the same results in multiple ways:
        expected_pks = ['3', '2', '1']

        results = self.sqs.all().order_by('pub_date').values('pk')
        self.assertListEqual([i['pk'] for i in results[1:11]], expected_pks)

        results = self.sqs.all().order_by('pub_date').values_list('pk')
        self.assertListEqual([i[0] for i in results[1:11]], expected_pks)

        results = self.sqs.all().order_by('pub_date').values_list('pk', flat=True)
        self.assertListEqual(results[1:11], expected_pks)

        self.assertEqual(len(connections['whoosh'].queries), 3)

    def test_manual_iter(self):
        self.sb.update(self.wmmi, self.sample_objs)
        results = self.sqs.auto_query('Indexed!')

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        results = [int(result.pk) for result in results._manual_iter()]
        self.assertEqual(sorted(results), [1, 2, 3])
        self.assertEqual(len(connections['whoosh'].queries), 1)

    def test_fill_cache(self):
        self.sb.update(self.wmmi, self.sample_objs)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        results = self.sqs.auto_query('Indexed!')
        self.assertEqual(len(results._result_cache), 0)
        self.assertEqual(len(connections['whoosh'].queries), 0)
        results._fill_cache(0, 10)
        self.assertEqual(len([result for result in results._result_cache if result is not None]), 3)
        self.assertEqual(len(connections['whoosh'].queries), 1)
        results._fill_cache(10, 20)
        self.assertEqual(len([result for result in results._result_cache if result is not None]), 3)
        self.assertEqual(len(connections['whoosh'].queries), 2)

    def test_cache_is_full(self):
        self.sb.update(self.wmmi, self.sample_objs)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        self.assertEqual(self.sqs._cache_is_full(), False)
        results = self.sqs.auto_query('Indexed!')
        [result for result in results]
        self.assertEqual(results._cache_is_full(), True)
        self.assertEqual(len(connections['whoosh'].queries), 1)

    def test_count(self):
        more_samples = []

        for i in range(1, 50):
            mock = MockModel()
            mock.id = i
            mock.author = 'daniel%s' % i
            mock.pub_date = date(2009, 2, 25) - timedelta(days=i)
            more_samples.append(mock)

        self.sb.update(self.wmmi, more_samples)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        results = self.sqs.all()
        self.assertEqual(len(results), 49)
        self.assertEqual(results._cache_is_full(), False)
        self.assertEqual(len(connections['whoosh'].queries), 1)

    def test_query_generation(self):
        sqs = self.sqs.filter(SQ(content=AutoQuery("hello world")) | SQ(title=AutoQuery("hello world")))
        self.assertEqual(sqs.query.build_query(), u"((hello world) OR title:(hello world))")

    def test_result_class(self):
        self.sb.update(self.wmmi, self.sample_objs)

        # Assert that we're defaulting to ``SearchResult``.
        sqs = self.sqs.all()
        self.assertTrue(isinstance(sqs[0], SearchResult))

        # Custom class.
        sqs = self.sqs.result_class(MockSearchResult).all()
        self.assertTrue(isinstance(sqs[0], MockSearchResult))

        # Reset to default.
        sqs = self.sqs.result_class(None).all()
        self.assertTrue(isinstance(sqs[0], SearchResult))
Beispiel #51
0
def search(request):
    # TODO: used forms in every search type

    def _render_search_form(form=None):
        return render(request, 'djangobb_forum/search_form.html', {
            'categories': Category.objects.all(),
            'form': form,
        })

    if not 'action' in request.GET:
        return _render_search_form(form=PostSearchForm())

    if request.GET.get("show_as") == "posts":
        show_as_posts = True
        template_name = 'djangobb_forum/search_posts.html'
    else:
        show_as_posts = False
        template_name = 'djangobb_forum/search_topics.html'

    context = {}

    # Create 'user viewable' pre-filtered topics/posts querysets
    viewable_category = Category.objects.all()
    topics = Topic.objects.all().order_by("-last_post__created")
    posts = Post.objects.all().order_by('-created')
    user = request.user
    if not user.is_superuser:
        user_groups = user.groups.all() or [
        ]  # need 'or []' for anonymous user otherwise: 'EmptyManager' object is not iterable
        viewable_category = viewable_category.filter(
            Q(groups__in=user_groups) | Q(groups__isnull=True))

        topics = Topic.objects.filter(forum__category__in=viewable_category)
        posts = Post.objects.filter(
            topic__forum__category__in=viewable_category)

    base_url = None
    _generic_context = True

    action = request.GET['action']
    if action == 'show_24h':
        date = timezone.now() - timedelta(days=1)
        if show_as_posts:
            context["posts"] = posts.filter(
                Q(created__gte=date) | Q(updated__gte=date))
        else:
            context["topics"] = topics.filter(
                Q(last_post__created__gte=date)
                | Q(last_post__updated__gte=date))
        _generic_context = False
    elif action == 'show_new':
        if not user.is_authenticated:
            raise Http404(
                "Search 'show_new' not available for anonymous user.")
        try:
            last_read = PostTracking.objects.get(user=user).last_read
        except PostTracking.DoesNotExist:
            last_read = None

        if last_read:
            if show_as_posts:
                context["posts"] = posts.filter(
                    Q(created__gte=last_read) | Q(updated__gte=last_read))
            else:
                context["topics"] = topics.filter(
                    Q(last_post__created__gte=last_read)
                    | Q(last_post__updated__gte=last_read))
            _generic_context = False
        else:
            #searching more than forum_settings.SEARCH_PAGE_SIZE in this way - not good idea :]
            topics_id = [
                topic.id for topic in topics[:forum_settings.SEARCH_PAGE_SIZE]
                if forum_extras.has_unreads(topic, user)
            ]
            topics = Topic.objects.filter(
                id__in=topics_id)  # to create QuerySet

    elif action == 'show_unanswered':
        topics = topics.filter(post_count=1)
    elif action == 'show_subscriptions':
        topics = topics.filter(subscribers__id=user.id)
    elif action == 'show_user':
        # Show all posts from user or topics started by user
        if not user.is_authenticated:
            raise Http404(
                "Search 'show_user' not available for anonymous user.")

        user_id = request.GET.get("user_id", user.id)
        try:
            user_id = int(user_id)
        except ValueError:
            raise SuspiciousOperation()

        if user_id != user.id:
            try:
                search_user = User.objects.get(id=user_id)
            except User.DoesNotExist:
                messages.error(request, _("Error: User unknown!"))
                return HttpResponseRedirect(request.path)
            messages.info(
                request,
                _("Filter by user '%(username)s'.") %
                {'username': search_user.username})

        if show_as_posts:
            posts = posts.filter(user__id=user_id)
        else:
            # show as topic
            topics = topics.filter(posts__user__id=user_id).order_by(
                "-last_post__created").distinct()

        base_url = "?action=show_user&user_id=%s&show_as=" % user_id
    elif action == 'search':
        form = PostSearchForm(request.GET)
        if not form.is_valid():
            return _render_search_form(form)

        keywords = form.cleaned_data['keywords']
        author = form.cleaned_data['author']
        forum = form.cleaned_data['forum']
        search_in = form.cleaned_data['search_in']
        sort_by = form.cleaned_data['sort_by']
        sort_dir = form.cleaned_data['sort_dir']

        query = SearchQuerySet().models(Post)

        if author:
            query = query.filter(author__username=author)

        if forum != '0':
            query = query.filter(forum__id=forum)

        if keywords:
            if search_in == 'all':
                query = query.filter(SQ(topic=keywords) | SQ(text=keywords))
            elif search_in == 'message':
                query = query.filter(text=keywords)
            elif search_in == 'topic':
                query = query.filter(topic=keywords)

        order = {
            '0': 'created',
            '1': 'author',
            '2': 'topic',
            '3': 'forum'
        }.get(sort_by, 'created')
        if sort_dir == 'DESC':
            order = '-' + order

        post_pks = query.values_list("pk", flat=True)

        if not show_as_posts:
            # TODO: We have here a problem to get a list of topics without double entries.
            # Maybe we must add a search index over topics?

            # Info: If whoosh backend used, setup HAYSTACK_ITERATOR_LOAD_PER_QUERY
            #    to a higher number to speed up
            context["topics"] = topics.filter(posts__in=post_pks).distinct()
        else:
            # FIXME: How to use the pre-filtered query from above?
            posts = posts.filter(pk__in=post_pks).order_by(order)
            context["posts"] = posts

        get_query_dict = request.GET.copy()
        get_query_dict.pop("show_as")
        base_url = "?%s&show_as=" % get_query_dict.urlencode()
        _generic_context = False

    if _generic_context:
        if show_as_posts:
            context["posts"] = posts.filter(
                topic__in=topics).order_by('-created')
        else:
            context["topics"] = topics

    if base_url is None:
        base_url = "?action=%s&show_as=" % action

    if show_as_posts:
        context['posts_page'] = get_page(context['posts'], request,
                                         forum_settings.SEARCH_PAGE_SIZE)
        context["as_topic_url"] = base_url + "topics"
        post_count = context["posts"].count()
        messages.success(request, _("Found %i posts.") % post_count)
    else:
        context['topics_page'] = get_page(context['topics'], request,
                                          forum_settings.SEARCH_PAGE_SIZE)
        context["as_post_url"] = base_url + "posts"
        topic_count = context["topics"].count()
        messages.success(request, _("Found %i topics.") % topic_count)

    return render(request, template_name, context)
Beispiel #52
0
def images_search(request):
    """
    View to make search of images.

    :param request: Request to serve
    """

    query = ''
    time_start = ''
    time_end = ''
    post = request.POST
    enable_checkboxes = False

    if request.method == 'GET' and request.GET.get('q') is not None:
        request.method = 'POST'
        enable_checkboxes = True
        post = {
            'q': request.GET['q'],
            'time_start': request.GET.get('time_start', ''),
            'time_end': request.GET.get('time_end', '')
        }

    if request.method == 'POST':

        # Check if session have to be deleted
        if post.get('clear_form'):
            request.session.flush()
            pass

        # New search, clear data stored in session
        results = None
        request.session['results_images'] = None
        form = SearchForm(post)
        restart = post.get('restart') is not None
        base_query = SearchQuerySet().models(Image).order_by('category_label')

        if form.is_valid():
            images = []
            categories_to_search = []
            query = form.cleaned_data['q'] if not restart else ''

            # Get categories to search and get left menu data
            for i in ImageCategory.objects.filter(visible_on_website=True):
                category_images = {}
                category_images["label_name"] = i.label
                category_images["label_code"] = i.value
                category_images["images"] = []
                search_set = base_query.filter(
                    category_label__exact=i.label,
                    ready_to_go=True).order_by('date')
                category_images["number_of_images"] = len(search_set)
                if restart or enable_checkboxes or post.get("checkbox" +
                                                            str(i.value)):
                    categories_to_search.append(i.label)

                images.append(category_images)

            images = sorted(images, key=lambda k: k["label_name"])

            time_start = post.get('time_start') if not restart else ''
            time_end = post.get('time_end') if not restart else ''

            # Options if query is provided
            if query != "":
                if time_start != "" and time_end != "":
                    results = \
                        base_query.filter(imgtext__icontains=query, ready_to_go=True,
                                                category_label__in=categories_to_search,
                                                date__gte=time_start,
                                                date__lte=time_end).\
                            order_by('date')

                elif time_start != "":
                    results = \
                        base_query.filter(imgtext__icontains=query, ready_to_go=True,
                                                category_label__in=categories_to_search,
                                                date__gte=time_start).\
                            order_by('date')

                elif time_end != "":
                    results = \
                        base_query.filter(imgtext__icontains=query, ready_to_go=True,
                                                category_label__in=categories_to_search,
                                                date__lte=time_end).\
                            order_by('date')

                else:
                    results = \
                        base_query.filter(imgtext__icontains=query, ready_to_go=True,
                                                category_label__in=categories_to_search).\
                            order_by('date')

            elif time_start != "" or time_end != "":
                if time_start != "" and time_end != "":
                    results = \
                        base_query.filter(ready_to_go=True,
                                                category_label__in=categories_to_search,
                                                date__gte=time_start,
                                                date__lte=time_end).\
                            order_by('date')

                elif time_start != "":
                    results = \
                        base_query.filter(ready_to_go=True,
                                                category_label__in=categories_to_search,
                                                date__gte=time_start).\
                            order_by('date')

                elif time_end != "":
                    results = \
                        base_query.filter(ready_to_go=True,
                                                category_label__in=categories_to_search,
                                                date__lte=time_end).\
                            order_by('date')

                else:
                    if len(categories_to_search) == 1:
                        return HttpResponseRedirect(
                            reverse('resources:images-category',
                                    kwargs={
                                        'category': categories_to_search.pop()
                                    }))
                    else:
                        results = base_query.all().filter(ready_to_go=True,
                                                            category_label__in=categories_to_search).\
                            order_by('date')

            else:
                if len(categories_to_search) > 1:
                    results = base_query.all().filter(ready_to_go=True,
                                                            category_label__in=categories_to_search).\
                            order_by('date')
                elif len(categories_to_search) == 1:
                    return HttpResponseRedirect(
                        reverse(
                            'resources:images-category',
                            kwargs={'category': categories_to_search.pop()}))

        if results is None:
            results = base_query.all()

        # Store results in session
        request.session['results_images'] = results
        request.session['images_images'] = images
        request.session['enabled_categories'] = categories_to_search
        request.session['query'] = query
        request.session['time_start'] = time_start
        request.session['time_end'] = time_end

    else:
        results = request.session.get('results_images')
        images = request.session.get('images_images')

    categorized = {
        cat: sorted(g, key=lambda x: _(x.title))
        for cat, g in groupby(results, key=lambda x: x.category_label)
    }

    return render(
        request, 'resources/images-search-results.html', {
            'results': results,
            'images': images,
            'query': request.session['query'],
            'time_start': request.session['time_start'],
            'time_end': request.session['time_end'],
            'enabled_categories': request.session['enabled_categories'],
            'categorized': categorized
        })
Beispiel #53
0
    def autocomplete(self, request, **kwargs):
        # Note: If the parameter in question (e.g. query, limit, etc.)
        # is not sent as part of the request, the request.GET.get()
        # method will set it to None unless a default is specified.
        query = request.GET.get('query', '')
        organism_uri = request.GET.get('organism')
        limit = request.GET.get('limit')

        if limit:
            try:
                # Make sure the input is already an integer
                # or can be coerced into one.
                limit = int(limit)
            except ValueError:
                logger.error("'limit' parameter passed was specified "
                             "incorrectly.")
                # Limit was specified incorrectly, so default to
                # GENES_API_RESULT_LIMIT setting.
                limit = GENES_API_RESULT_LIMIT
        else:
            limit = GENES_API_RESULT_LIMIT

        # We want to sort results by three fields: First by search score,
        # then by name length (standard_name if present, if not then
        # systematic_name), and finally by this name's alphabetical order.
        # We sort by gene name length because a long gene name and
        # a short gene name can have the same score if they contain the n-gram.
        # A user can always type more to get the long one, but they can't type
        # less to get the short one. By returning the shortest first, we make
        # sure that this choice is always available to the user, even if a
        # limit is applied.
        #
        # *Note: We use SearchQuerySet's order_by() function to sort by these
        # three fields, but this current implementation is Elasticsearch
        # specific. (Elasticsearch uses '_score' while it is simply 'score' in
        # Solr). At some point we might want to expand this to be compatible
        # with other search engines, like Solr, Xapian and Whoosh.
        # See Haystack issue here:
        # https://github.com/django-haystack/django-haystack/issues/1431
        sqs = SearchQuerySet().models(Gene).autocomplete(
            wall_of_name_auto=query).order_by('-_score', 'name_length',
                                              'wall_of_name_auto')

        if organism_uri:
            organism = OrganismResource().get_via_uri(organism_uri, request)
            sqs = sqs.filter(organism=organism)

        suggestions = []

        # Get slice of sqs for 'limit' specified (or use full sqs if no limit
        # was specified).
        for result in sqs[:limit]:
            gene = result.object
            suggestions.append({
                'id': gene.id,
                'score': result.score,
                'entrezid': gene.entrezid,
                'standard_name': gene.standard_name,
                'systematic_name': gene.systematic_name,
                'description': gene.description
            })

        # Return a JSON object instead of an array, as returning an array
        # could make the information vulnerable to an XSS attack.
        response = {'results': suggestions}
        return self.create_response(request, response)
Beispiel #54
0
class SearchTopicIndexTest(TestCase):

    def setUp(self):
        utils.cache_clear()
        self.topic_sqs = SearchQuerySet().models(Topic)
        self.now = timezone.now()
        self.yesterday = timezone.now() - datetime.timedelta(days=1)
        self.tomorrow = timezone.now() + datetime.timedelta(days=1)

    def test_index_queryset_excludes_private_topics(self):
        """
        index_queryset should exclude private topics
        """
        utils.create_private_topic()
        self.assertEqual(len(TopicIndex().index_queryset()), 0)

        category = utils.create_category()
        utils.create_topic(category)
        self.assertEqual(len(TopicIndex().index_queryset()), 1)

    def test_indexing_excludes_private_topics(self):
        """
        rebuild_index command should exclude private topics
        """
        utils.create_private_topic()
        category = utils.create_category()
        topic = utils.create_topic(category)
        rebuild_index()

        self.assertEqual([s.object for s in self.topic_sqs], [topic])

    def test_indexing_is_removed(self):
        """
        Should set the removed flag when either\
        topic, subcategory or category are removed
        """
        main_category = utils.create_category()
        category = utils.create_category(parent=main_category)
        topic = utils.create_topic(category)

        rebuild_index()
        self.assertEqual(
            len(self.topic_sqs.filter(is_removed=False)), 1)

        topic.is_removed = True
        topic.save()
        rebuild_index()
        self.assertEqual(
            len(self.topic_sqs.filter(is_removed=False)), 0)

        category.is_removed = True
        category.save()
        topic.is_removed = False
        topic.save()
        rebuild_index()
        self.assertEqual(
            len(self.topic_sqs.filter(is_removed=False)), 0)

        main_category.is_removed = True
        main_category.save()
        category.is_removed = False
        category.save()
        topic.is_removed = False
        topic.save()
        rebuild_index()
        self.assertEqual(
            len(self.topic_sqs.filter(is_removed=False)), 0)

        main_category.is_removed = False
        main_category.save()
        rebuild_index()
        self.assertEqual(
            len(self.topic_sqs.filter(is_removed=False)), 1)

    def test_indexing_slug_empty(self):
        """
        Should store the slug as an empty string
        """
        category = utils.create_category()
        topic = utils.create_topic(category)
        topic.slug = ''
        topic.save()
        rebuild_index()
        self.assertEqual(len(self.topic_sqs.all()), 1)
        self.assertEqual(
            list(self.topic_sqs.all())[0]
            .get_stored_fields()['slug'],
            '')

    def test_indexing_main_category_name(self):
        """
        Should store the main category name
        """
        main_category = utils.create_category()
        category = utils.create_category(parent=main_category)
        utils.create_topic(category)
        rebuild_index()
        self.assertEqual(len(self.topic_sqs.all()), 1)
        self.assertEqual(
            list(self.topic_sqs.all())[0]
            .get_stored_fields()['main_category_name'],
            main_category.title)

    def test_indexing_text_include_comments(self):
        """
        Should include topic title and all comments
        """
        category = utils.create_category()
        topic = utils.create_topic(category, title='my title')
        utils.create_comment(topic=topic, comment_html='<span>foo</span>')
        utils.create_comment(topic=topic, comment_html='<b>bar</b>')
        rebuild_index()
        self.assertEqual(len(self.topic_sqs.all()), 1)
        self.assertEqual(
            len(self.topic_sqs.filter(text='my title foo bar')), 1)
        self.assertEqual(
            len(self.topic_sqs.filter(text='bar')), 1)
        self.assertEqual(
            len(self.topic_sqs.filter(text='<b>')), 0)
        self.assertEqual(
            len(self.topic_sqs.filter(text='span')), 0)

    def test_indexing_text_template(self):
        """
        Should include topic title and all comments
        """
        category = utils.create_category()
        topic = utils.create_topic(category, title='my title')
        utils.create_comment(topic=topic, comment_html='<span>foo</span>')
        utils.create_comment(topic=topic, comment_html='<b>bar</b>')
        self.assertEqual(
            render_to_string(
                'search/indexes/spirit_topic/topic_text.txt',
                context={'object': topic}),
            'my title\n\nbar\n\nfoo\n\n')

    def test_indexing_build_queryset_by_topic(self):
        """
        Should update topics based on modified times
        """
        main_category = utils.create_category(
            reindex_at=self.yesterday)
        category = utils.create_category(
            parent=main_category, reindex_at=self.yesterday)
        topic = utils.create_topic(
            category,
            reindex_at=self.yesterday, last_active=self.yesterday)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now)), 0)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now, end_date=self.tomorrow)), 0)

        topic.reindex_at = self.tomorrow
        topic.save()
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now)), 1)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now, end_date=self.tomorrow)), 1)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now, end_date=self.now)), 0)

    def test_indexing_build_queryset_by_comment(self):
        """
        Should update topics based on modified times
        """
        main_category = utils.create_category(
            reindex_at=self.yesterday)
        category = utils.create_category(
            parent=main_category, reindex_at=self.yesterday)
        topic = utils.create_topic(
            category,
            reindex_at=self.yesterday, last_active=self.yesterday)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now)), 0)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now, end_date=self.tomorrow)), 0)

        topic.last_active = self.tomorrow
        topic.save()
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now)), 1)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now, end_date=self.tomorrow)), 1)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now, end_date=self.now)), 0)

    def test_indexing_build_queryset_by_category(self):
        """
        Should update topics based on modified times
        """
        main_category = utils.create_category(
            reindex_at=self.yesterday)
        category = utils.create_category(
            parent=main_category, reindex_at=self.yesterday)
        utils.create_topic(
            category,
            reindex_at=self.yesterday, last_active=self.yesterday)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now)), 0)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now, end_date=self.tomorrow)), 0)

        category.reindex_at = self.tomorrow
        category.save()
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now)), 1)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now, end_date=self.tomorrow)), 1)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now, end_date=self.now)), 0)

    def test_indexing_build_queryset_by_subcategory(self):
        """
        Should update topics based on modified times
        """
        main_category = utils.create_category(
            reindex_at=self.yesterday)
        category = utils.create_category(
            parent=main_category, reindex_at=self.yesterday)
        utils.create_topic(
            category,
            reindex_at=self.yesterday, last_active=self.yesterday)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now)), 0)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now, end_date=self.tomorrow)), 0)

        main_category.reindex_at = self.tomorrow
        main_category.save()
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now)), 1)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now, end_date=self.tomorrow)), 1)
        self.assertEqual(
            len(TopicIndex().build_queryset(start_date=self.now, end_date=self.now)), 0)
class LiveWhooshMoreLikeThisTestCase(WhooshTestCase):
    fixtures = ['bulk_data.json']

    def setUp(self):
        super(LiveWhooshMoreLikeThisTestCase, self).setUp()

        # Stow.
        self.old_ui = connections['whoosh'].get_unified_index()
        self.ui = UnifiedIndex()
        self.wmmi = WhooshMockSearchIndex()
        self.wamsi = WhooshAnotherMockSearchIndex()
        self.ui.build(indexes=[self.wmmi, self.wamsi])
        self.sb = connections['whoosh'].get_backend()
        connections['whoosh']._index = self.ui

        self.sb.setup()
        self.raw_whoosh = self.sb.index
        self.parser = QueryParser(self.sb.content_field_name,
                                  schema=self.sb.schema)
        self.sb.delete_index()

        self.wmmi.update()
        self.wamsi.update()

        self.sqs = SearchQuerySet('whoosh')

    def tearDown(self):
        connections['whoosh']._index = self.old_ui
        super(LiveWhooshMoreLikeThisTestCase, self).tearDown()

    # We expect failure here because, despite not changing the code, Whoosh
    # 2.5.1 returns incorrect counts/results. Huzzah.
    @unittest.expectedFailure
    def test_more_like_this(self):
        mlt = self.sqs.more_like_this(MockModel.objects.get(pk=22))
        self.assertEqual(mlt.count(), 22)
        self.assertEqual(
            sorted([result.pk for result in mlt]),
            sorted([
                u'9', u'8', u'7', u'6', u'5', u'4', u'3', u'2', u'1', u'21',
                u'20', u'19', u'18', u'17', u'16', u'15', u'14', u'13', u'12',
                u'11', u'10', u'23'
            ]))
        self.assertEqual(len([result.pk for result in mlt]), 22)

        alt_mlt = self.sqs.filter(name='daniel3').more_like_this(
            MockModel.objects.get(pk=13))
        self.assertEqual(alt_mlt.count(), 8)
        self.assertEqual(
            sorted([result.pk for result in alt_mlt]),
            sorted([u'4', u'3', u'22', u'19', u'17', u'16', u'10', u'23']))
        self.assertEqual(len([result.pk for result in alt_mlt]), 8)

        alt_mlt_with_models = self.sqs.models(MockModel).more_like_this(
            MockModel.objects.get(pk=11))
        self.assertEqual(alt_mlt_with_models.count(), 22)
        self.assertEqual(
            sorted([result.pk for result in alt_mlt_with_models]),
            sorted([
                u'9', u'8', u'7', u'6', u'5', u'4', u'3', u'2', u'1', u'22',
                u'21', u'20', u'19', u'18', u'17', u'16', u'15', u'14', u'13',
                u'12', u'10', u'23'
            ]))
        self.assertEqual(len([result.pk for result in alt_mlt_with_models]),
                         22)

        if hasattr(MockModel.objects, 'defer'):
            # Make sure MLT works with deferred bits.
            mi = MockModel.objects.defer('foo').get(pk=21)
            self.assertEqual(mi._deferred, True)
            deferred = self.sqs.models(MockModel).more_like_this(mi)
            self.assertEqual(deferred.count(), 0)
            self.assertEqual([result.pk for result in deferred], [])
            self.assertEqual(len([result.pk for result in deferred]), 0)

        # Ensure that swapping the ``result_class`` works.
        self.assertTrue(
            isinstance(
                self.sqs.result_class(MockSearchResult).more_like_this(
                    MockModel.objects.get(pk=21))[0], MockSearchResult))
Beispiel #56
0
 def results_for_members(self, team):
     base_qs = SearchQuerySet().models(models.TeamVideo)
     public = SQ(is_public=True)
     mine = SQ(is_public=False, owned_by_team_id=team.pk)
     return base_qs.filter(public | mine)
Beispiel #57
0
    def build_haystack_filters(self, parameters):
        from haystack.inputs import Raw
        from haystack.query import SearchQuerySet, SQ  # noqa

        sqs = None

        # Retrieve Query Params

        # Text search
        query = parameters.get('q', None)

        # Types and subtypes to filter (map, layer, vector, etc)
        type_facets = parameters.getlist("type__in", [])

        # If coming from explore page, add type filter from resource_name
        resource_filter = self._meta.resource_name.rstrip("s")
        if resource_filter != "base" and resource_filter not in type_facets:
            type_facets.append(resource_filter)

        # Publication date range (start,end)
        date_end = parameters.get("date__lte", None)
        date_start = parameters.get("date__gte", None)

        # Topic category filter
        category = parameters.getlist("category__identifier__in")

        # Keyword filter
        keywords = parameters.getlist("keywords__slug__in")

        # Region filter
        regions = parameters.getlist("regions__name__in")

        # Owner filters
        owner = parameters.getlist("owner__username__in")

        # Sort order
        sort = parameters.get("order_by", "relevance")

        # Geospatial Elements
        bbox = parameters.get("extent", None)

        # Filter by Type and subtype
        if type_facets is not None:

            types = []
            subtypes = []

            for type in type_facets:
                if type in ["map", "layer", "document", "user"]:
                    # Type is one of our Major Types (not a sub type)
                    types.append(type)
                elif type in LAYER_SUBTYPES.keys():
                    subtypes.append(type)

            if len(subtypes) > 0:
                types.append("layer")
                sqs = SearchQuerySet().narrow("subtype:%s" %
                                              ','.join(map(str, subtypes)))

            if len(types) > 0:
                sqs = (SearchQuerySet() if sqs is None else sqs).narrow(
                    "type:%s" % ','.join(map(str, types)))

        # Filter by Query Params
        # haystack bug? if boosted fields aren't included in the
        # query, then the score won't be affected by the boost
        if query:
            if query.startswith('"') or query.startswith('\''):
                # Match exact phrase
                phrase = query.replace('"', '')
                sqs = (SearchQuerySet() if sqs is None else sqs).filter(
                    SQ(title__exact=phrase) |
                    SQ(description__exact=phrase) |
                    SQ(content__exact=phrase)
                )
            else:
                words = [
                    w for w in re.split(
                        '\W',
                        query,
                        flags=re.UNICODE) if w]
                for i, search_word in enumerate(words):
                    if i == 0:
                        sqs = (SearchQuerySet() if sqs is None else sqs) \
                            .filter(
                            SQ(title=Raw(search_word)) |
                            SQ(description=Raw(search_word)) |
                            SQ(content=Raw(search_word))
                        )
                    elif search_word in ["AND", "OR"]:
                        pass
                    elif words[i - 1] == "OR":  # previous word OR this word
                        sqs = sqs.filter_or(
                            SQ(title=Raw(search_word)) |
                            SQ(description=Raw(search_word)) |
                            SQ(content=Raw(search_word))
                        )
                    else:  # previous word AND this word
                        sqs = sqs.filter(
                            SQ(title=Raw(search_word)) |
                            SQ(description=Raw(search_word)) |
                            SQ(content=Raw(search_word))
                        )

        # filter by category
        if category:
            sqs = (SearchQuerySet() if sqs is None else sqs).narrow(
                'category:%s' % ','.join(map(str, category)))

        # filter by keyword: use filter_or with keywords_exact
        # not using exact leads to fuzzy matching and too many results
        # using narrow with exact leads to zero results if multiple keywords
        # selected
        if keywords:
            for keyword in keywords:
                sqs = (
                    SearchQuerySet() if sqs is None else sqs).filter_or(
                    keywords_exact=keyword)

        # filter by regions: use filter_or with regions_exact
        # not using exact leads to fuzzy matching and too many results
        # using narrow with exact leads to zero results if multiple keywords
        # selected
        if regions:
            for region in regions:
                sqs = (
                    SearchQuerySet() if sqs is None else sqs).filter_or(
                    regions_exact__exact=region)

        # filter by owner
        if owner:
            sqs = (
                SearchQuerySet() if sqs is None else sqs).narrow(
                    "owner__username:%s" % ','.join(map(str, owner)))

        # filter by date
        if date_start:
            sqs = (SearchQuerySet() if sqs is None else sqs).filter(
                SQ(date__gte=date_start)
            )

        if date_end:
            sqs = (SearchQuerySet() if sqs is None else sqs).filter(
                SQ(date__lte=date_end)
            )

        # Filter by geographic bounding box
        if bbox:
            left, bottom, right, top = bbox.split(',')
            sqs = (
                SearchQuerySet() if sqs is None else sqs).exclude(
                SQ(
                    bbox_top__lte=bottom) | SQ(
                    bbox_bottom__gte=top) | SQ(
                    bbox_left__gte=right) | SQ(
                        bbox_right__lte=left))

        # Apply sort
        if sort.lower() == "-date":
            sqs = (
                SearchQuerySet() if sqs is None else sqs).order_by("-date")
        elif sort.lower() == "date":
            sqs = (
                SearchQuerySet() if sqs is None else sqs).order_by("date")
        elif sort.lower() == "title":
            sqs = (SearchQuerySet() if sqs is None else sqs).order_by(
                "title_sortable")
        elif sort.lower() == "-title":
            sqs = (SearchQuerySet() if sqs is None else sqs).order_by(
                "-title_sortable")
        elif sort.lower() == "-popular_count":
            sqs = (SearchQuerySet() if sqs is None else sqs).order_by(
                "-popular_count")
        else:
            sqs = (
                SearchQuerySet() if sqs is None else sqs).order_by("-date")

        return sqs
Beispiel #58
0
def do_site_search(q, allow_redirect=False, request=None):
    if q.strip() == "":
        return []
    
    results = []
    
    from bill.models import Bill
    from vote.models import Vote
    if "pass" in q or "fail" in q or "vote" in q:
        results.append({
            "title": "Tracking Federal Legislation",
            "href": "/start",
            "noun": "feeds",
            "results": [
                {"href": f.link,
                 "label": f.title,
                 "obj": f,
                 "feed": f,
                 "secondary": False }
                for f in (
                    Bill.EnactedBillsFeed(), Bill.ActiveBillsExceptIntroductionsFeed(), Bill.ComingUpFeed(), Vote.AllVotesFeed(),
                    )
                ]
            })
    
    from haystack.query import SearchQuerySet
    from events.models import Feed

    from person.models import RoleType
    sqs = SearchQuerySet().using("person")\
        .filter(
            indexed_model_name__in=["Person"],
            all_role_types__in=(RoleType.representative, RoleType.senator),
            content=q)
    if 'XapianEngine' not in settings.HAYSTACK_CONNECTIONS['person']['ENGINE']:
        # Xapian doesn't provide a 'score' so we can't do this when debugging.
        sqs = sqs.order_by('-is_currently_serving', '-score')
    results.append({
        "title": "Members of Congress",
        "href": "/congress/members/all",
        "qsarg": "name",
        "noun": "Members of Congress",
        "results": [
            {"href": p.object.get_absolute_url(),
             "label": p.object.name,
             "obj": p.object,
             "feed": p.object.get_feed(),
             "secondary": p.object.get_current_role() == None }
            for p in sqs[0:9]]
        })
       
    import us
    results.append({
        "title": "States",
        "href": "/congress/members",
        "noun": "states",
        "results": sorted([{"href": "/congress/members/%s" % s, "label": us.statenames[s] }
            for s in us.statenames
            if us.statenames[s].lower().startswith(q.lower())
            ], key=lambda p : p["label"])})
    
    # search committees -- name must contain all of the words in the
    # search query (e.g. "rules committee" should match "committee on rules")
    from committee.models import Committee
    committees_qs = Committee.objects.filter(obsolete=False)
    for word in q.split(" "):
        committees_qs = committees_qs.filter(name__icontains=word)
    results.append({
        "title": "Congressional Committees",
        "href": "/congress/committees",
        "noun": "committees in Congress",
        "results": sorted([
            {"href": c.get_absolute_url(),
             "label": c.fullname,
             "feed": c.get_feed(),
             "obj": c,
             "secondary": c.committee != None}
            for c in committees_qs
            ], key=lambda c : c["label"])
        })
       
    from settings import CURRENT_CONGRESS
    from bill.search import parse_bill_citation
    bill = parse_bill_citation(q)
    congress = "__ALL__"
    if not bill or not allow_redirect:
        # query Solr w/ the boosted field
        from haystack.inputs import AutoQuery
        from haystack.query import SQ
        q = SearchQuerySet().using("bill").filter(indexed_model_name__in=["Bill"])\
            .filter( SQ(text=AutoQuery(q)) | SQ(text_boosted=AutoQuery(q)) )

        # restrict to current bills if any (at least 10) bills match
        q1 = q.filter(congress=CURRENT_CONGRESS)
        if q1.count() >= 10:
            q = q1
            congress = str(CURRENT_CONGRESS)

        bills = [\
            {"href": b.object.get_absolute_url(),
             "label": b.object.title,
             "obj": b.object,
             "feed": b.object.get_feed() if b.object.is_alive else None,
             "secondary": b.object.congress != CURRENT_CONGRESS }
            for b in q[0:9]]
    else:
        url = bill.get_absolute_url()
        if request.GET.get("track"): url += "#track"
        return HttpResponseRedirect(url)
    results.append({
        "title": "Bills and Resolutions",
        "href": "/congress/bills/browse",
        "qsarg": "congress=%s&text" % congress,
        "noun": "federal bills or resolutions",
        "results": bills})

    # subject terms, but exclude subject terms that look like committee names because
    # that is confusing to also see with committee results
    from bill.models import BillTerm, TermType
    results.append({
        "title": "Subject Areas",
        "href": "/congress/bills",
        "noun": "subject areas",
        "results": [
            {"href": p.get_absolute_url(),
             "label": p.name,
             "obj": p,
             "feed": p.get_feed(),
             "secondary": not p.is_top_term() }
            for p in BillTerm.objects.filter(name__icontains=q, term_type=TermType.new).exclude(name__contains=" Committee on ")[0:9]]
        })
    
    # in each group, make sure the secondary results are placed last, but otherwise preserve order
    for grp in results:
        for i, obj in enumerate(grp["results"]):
           obj["index"] = i
        grp["results"].sort(key = lambda o : (o.get("secondary", False), o["index"]))
    
    # sort categories first by whether all results are secondary results, then by number of matches (fewest first, if greater than zero)
    results.sort(key = lambda c : (
        len([d for d in c["results"] if d.get("secondary", False) == False]) == 0,
        len(c["results"]) == 0,
        len(c["results"])))
        
    return results
Beispiel #59
0
class LiveWhooshRamStorageTestCase(TestCase):
    def setUp(self):
        super(LiveWhooshRamStorageTestCase, self).setUp()

        # Stow.
        self.old_whoosh_storage = getattr(settings, 'HAYSTACK_WHOOSH_STORAGE',
                                          'file')
        settings.HAYSTACK_WHOOSH_STORAGE = 'ram'

        self.site = SearchSite()
        self.sb = SearchBackend(site=self.site)
        self.wrtsi = WhooshRoundTripSearchIndex(MockModel, backend=self.sb)
        self.site.register(MockModel, WhooshRoundTripSearchIndex)

        # Stow.
        import haystack
        self.old_debug = settings.DEBUG
        settings.DEBUG = True
        self.old_site = haystack.site
        haystack.site = self.site

        self.sb.setup()
        self.raw_whoosh = self.sb.index
        self.parser = QueryParser(self.sb.content_field_name,
                                  schema=self.sb.schema)

        self.sqs = SearchQuerySet(site=self.site)

        # Wipe it clean.
        self.sqs.query.backend.clear()

        # Fake indexing.
        mock = MockModel()
        mock.id = 1
        self.sb.update(self.wrtsi, [mock])

    def tearDown(self):
        self.sqs.query.backend.clear()

        settings.HAYSTACK_WHOOSH_STORAGE = self.old_whoosh_storage

        import haystack
        haystack.site = self.old_site
        settings.DEBUG = self.old_debug

        super(LiveWhooshRamStorageTestCase, self).tearDown()

    def test_ram_storage(self):
        results = self.sqs.filter(id='core.mockmodel.1')

        # Sanity check.
        self.assertEqual(results.count(), 1)

        # Check the individual fields.
        result = results[0]
        self.assertEqual(result.id, 'core.mockmodel.1')
        self.assertEqual(result.text, 'This is some example text.')
        self.assertEqual(result.name, 'Mister Pants')
        self.assertEqual(result.is_active, True)
        self.assertEqual(result.post_count, 25)
        self.assertEqual(result.average_rating, 3.6)
        self.assertEqual(result.pub_date, datetime(2009, 11, 21, 0, 0))
        self.assertEqual(result.created, datetime(2009, 11, 21, 21, 31, 00))
        self.assertEqual(result.tags,
                         ['staff', 'outdoor', 'activist', 'scientist'])
        self.assertEqual(result.sites, [u'3', u'5', u'1'])
        self.assertEqual(result.empty_list, [])
Beispiel #60
0
class LiveWhooshSearchQuerySetTestCase(TestCase):
    def setUp(self):
        super(LiveWhooshSearchQuerySetTestCase, self).setUp()

        # Stow.
        temp_path = os.path.join('tmp', 'test_whoosh_query')
        self.old_whoosh_path = settings.HAYSTACK_CONNECTIONS['whoosh']['PATH']
        settings.HAYSTACK_CONNECTIONS['whoosh']['PATH'] = temp_path

        self.old_ui = connections['whoosh'].get_unified_index()
        self.ui = UnifiedIndex()
        self.wmmi = WhooshMockSearchIndex()
        self.ui.build(indexes=[self.wmmi])
        self.sb = connections['whoosh'].get_backend()
        connections['whoosh']._index = self.ui

        self.sb.setup()
        self.raw_whoosh = self.sb.index
        self.parser = QueryParser(self.sb.content_field_name,
                                  schema=self.sb.schema)
        self.sb.delete_index()

        self.sample_objs = []

        for i in range(1, 4):
            mock = MockModel()
            mock.id = i
            mock.author = 'daniel%s' % i
            mock.pub_date = date(2009, 2, 25) - timedelta(days=i)
            self.sample_objs.append(mock)

        self.sq = connections['whoosh'].get_query()
        self.sqs = SearchQuerySet('whoosh')

    def tearDown(self):
        if os.path.exists(settings.HAYSTACK_CONNECTIONS['whoosh']['PATH']):
            shutil.rmtree(settings.HAYSTACK_CONNECTIONS['whoosh']['PATH'])

        settings.HAYSTACK_CONNECTIONS['whoosh']['PATH'] = self.old_whoosh_path
        connections['whoosh']._index = self.old_ui
        super(LiveWhooshSearchQuerySetTestCase, self).tearDown()

    def test_various_searchquerysets(self):
        self.sb.update(self.wmmi, self.sample_objs)

        sqs = self.sqs.filter(content='Index')
        self.assertEqual(sqs.query.build_query(), u'(Index)')
        self.assertEqual(len(sqs), 3)

        sqs = self.sqs.auto_query('Indexed!')
        self.assertEqual(sqs.query.build_query(), u"('Indexed!')")
        self.assertEqual(len(sqs), 3)

        sqs = self.sqs.auto_query('Indexed!').filter(
            pub_date__lte=date(2009, 8, 31))
        self.assertEqual(sqs.query.build_query(),
                         u"(('Indexed!') AND pub_date:([to 20090831000000]))")
        self.assertEqual(len(sqs), 3)

        sqs = self.sqs.auto_query('Indexed!').filter(
            pub_date__lte=date(2009, 2, 23))
        self.assertEqual(sqs.query.build_query(),
                         u"(('Indexed!') AND pub_date:([to 20090223000000]))")
        self.assertEqual(len(sqs), 2)

        sqs = self.sqs.auto_query('Indexed!').filter(
            pub_date__lte=date(2009, 2, 25)).filter(
                django_id__in=[1, 2]).exclude(name='daniel1')
        self.assertEqual(
            sqs.query.build_query(),
            u'((\'Indexed!\') AND pub_date:([to 20090225000000]) AND django_id:(1 OR 2) AND NOT (name:(daniel1)))'
        )
        self.assertEqual(len(sqs), 1)

        sqs = self.sqs.auto_query('re-inker')
        self.assertEqual(sqs.query.build_query(), u"('re-inker')")
        self.assertEqual(len(sqs), 0)

        sqs = self.sqs.auto_query('0.7 wire')
        self.assertEqual(sqs.query.build_query(), u"('0.7' wire)")
        self.assertEqual(len(sqs), 0)

        sqs = self.sqs.auto_query("daler-rowney pearlescent 'bell bronze'")
        self.assertEqual(sqs.query.build_query(),
                         u"('daler-rowney' pearlescent 'bell bronze')")
        self.assertEqual(len(sqs), 0)

        sqs = self.sqs.models(MockModel)
        self.assertEqual(sqs.query.build_query(), u'*')
        self.assertEqual(len(sqs), 3)

    def test_all_regression(self):
        sqs = SearchQuerySet('whoosh')
        self.assertEqual([result.pk for result in sqs], [])

        self.sb.update(self.wmmi, self.sample_objs)
        self.assertTrue(self.sb.index.doc_count() > 0)

        sqs = SearchQuerySet('whoosh')
        self.assertEqual(len(sqs), 3)
        self.assertEqual(sorted([result.pk for result in sqs]),
                         [u'1', u'2', u'3'])

        try:
            sqs = repr(SearchQuerySet('whoosh'))
        except:
            self.fail()

    def test_regression_space_query(self):
        self.sb.update(self.wmmi, self.sample_objs)
        self.assertTrue(self.sb.index.doc_count() > 0)

        sqs = SearchQuerySet('whoosh').auto_query(" ")
        self.assertEqual(len(sqs), 3)
        sqs = SearchQuerySet('whoosh').filter(content=" ")
        self.assertEqual(len(sqs), 0)

    def test_iter(self):
        self.sb.update(self.wmmi, self.sample_objs)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        sqs = self.sqs.auto_query('Indexed!')
        results = [int(result.pk) for result in sqs]
        self.assertEqual(sorted(results), [1, 2, 3])
        self.assertEqual(len(connections['whoosh'].queries), 1)

    def test_slice(self):
        self.sb.update(self.wmmi, self.sample_objs)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        results = self.sqs.auto_query('Indexed!')
        self.assertEqual(sorted([int(result.pk) for result in results[1:3]]),
                         [1, 2])
        self.assertEqual(len(connections['whoosh'].queries), 1)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        results = self.sqs.auto_query('Indexed!')
        self.assertEqual(int(results[0].pk), 1)
        self.assertEqual(len(connections['whoosh'].queries), 1)

    def test_manual_iter(self):
        self.sb.update(self.wmmi, self.sample_objs)
        results = self.sqs.auto_query('Indexed!')

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        results = [int(result.pk) for result in results._manual_iter()]
        self.assertEqual(sorted(results), [1, 2, 3])
        self.assertEqual(len(connections['whoosh'].queries), 1)

    def test_fill_cache(self):
        self.sb.update(self.wmmi, self.sample_objs)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        results = self.sqs.auto_query('Indexed!')
        self.assertEqual(len(results._result_cache), 0)
        self.assertEqual(len(connections['whoosh'].queries), 0)
        results._fill_cache(0, 10)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 3)
        self.assertEqual(len(connections['whoosh'].queries), 1)
        results._fill_cache(10, 20)
        self.assertEqual(
            len([
                result for result in results._result_cache
                if result is not None
            ]), 3)
        self.assertEqual(len(connections['whoosh'].queries), 2)

    def test_cache_is_full(self):
        self.sb.update(self.wmmi, self.sample_objs)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        self.assertEqual(self.sqs._cache_is_full(), False)
        results = self.sqs.auto_query('Indexed!')
        [result for result in results]
        self.assertEqual(results._cache_is_full(), True)
        self.assertEqual(len(connections['whoosh'].queries), 1)

    def test_count(self):
        more_samples = []

        for i in range(1, 50):
            mock = MockModel()
            mock.id = i
            mock.author = 'daniel%s' % i
            mock.pub_date = date(2009, 2, 25) - timedelta(days=i)
            more_samples.append(mock)

        self.sb.update(self.wmmi, more_samples)

        reset_search_queries()
        self.assertEqual(len(connections['whoosh'].queries), 0)
        results = self.sqs.all()
        self.assertEqual(len(results), 49)
        self.assertEqual(results._cache_is_full(), False)
        self.assertEqual(len(connections['whoosh'].queries), 1)

    def test_query_generation(self):
        sqs = self.sqs.filter(
            SQ(content=AutoQuery("hello world"))
            | SQ(title=AutoQuery("hello world")))
        self.assertEqual(sqs.query.build_query(),
                         u"((hello world) OR title:(hello world))")

    def test_result_class(self):
        self.sb.update(self.wmmi, self.sample_objs)

        # Assert that we're defaulting to ``SearchResult``.
        sqs = self.sqs.all()
        self.assertTrue(isinstance(sqs[0], SearchResult))

        # Custom class.
        sqs = self.sqs.result_class(MockSearchResult).all()
        self.assertTrue(isinstance(sqs[0], MockSearchResult))

        # Reset to default.
        sqs = self.sqs.result_class(None).all()
        self.assertTrue(isinstance(sqs[0], SearchResult))