Beispiel #1
0
def render_cosinnus_topics(topics, seperator_word=None):
    """ Renders a list of media-tag Topics as html <a> tags linking to the topics search page, 
        with proper labels and seperators 
        @param topics: A single int/str number or list or comma-seperated list of int/str numbers that are IDs 
                        in ``BaseTagObject.TOPIC_CHOICES``
    """
    if not topics:
        return ''
    choices_dict = dict(BaseTagObject.TOPIC_CHOICES)

    topics = ensure_list_of_ints(topics)

    template = """<a href="%(url)s?topics=%(topic)d">%(label)s</a>"""
    search_url = reverse('cosinnus:search')
    seperator_word = ' %s ' % seperator_word if seperator_word else ', '

    rendered_topics = [
        template % {
            'url': search_url,
            'topic': topic,
            'label': choices_dict[topic],
        } for topic in topics
    ]

    return seperator_word.join(rendered_topics)
Beispiel #2
0
 def _filter_media_tags(self, sqs):
     topics = ensure_list_of_ints(self.cleaned_data.get('topics', []))
     if topics:
         sqs = sqs.filter_and(mt_topics__in=topics)
     location = self.cleaned_data.get('location', None)
     if location:
         sqs = sqs.filter_and(mt_location__contains=location.lower())
     start = self.cleaned_data.get('valid_start', None)
     if start:
         sqs = sqs.filter_and(mt_valid_start__gte=start)
     end = self.cleaned_data.get('valid_end', None)
     if end:
         sqs = sqs.filter_and(mt_valid_end__gte=end)
     return sqs
Beispiel #3
0
    def get_queryset(self):
        qs = super(OfferListView, self).get_queryset()

        # additional category AND filter:
        categories = ensure_list_of_ints(
            self.request.GET.getlist('categories'))

        if categories:
            qs = qs.filter(categories__in=categories)

        self.unfiltered_qs = qs
        if self.offer_view == 'all':
            qs = qs.filter(is_active=True)
        elif self.offer_view == 'mine':
            qs = qs.filter(creator=self.request.user)
        self.queryset = qs
        return qs
Beispiel #4
0
def map_search_endpoint(request, filter_group_id=None):
    """ Maps API search endpoint using haystack search results. For parameters see ``MAP_SEARCH_PARAMETERS``
        returns JSON with the contents of type ``HaystackMapResult``
        
        @param filter_group_id: Will filter all items by group relation, where applicable 
                (i.e. users are filtered by group memberships for that group, events as events in that group)
    """
    implicit_ignore_location = not any([
        loc_param in request.GET
        for loc_param in ['sw_lon', 'sw_lat', 'ne_lon', 'ne_lat']
    ])
    params = _collect_parameters(request.GET, MAP_SEARCH_PARAMETERS)
    query = force_text(params['q'])
    limit = params['limit']
    page = params['page']
    item_id = params['item']
    prefer_own_portal = getattr(settings, 'MAP_API_HACKS_PREFER_OWN_PORTAL',
                                False)

    if not is_number(limit) or limit < 0:
        return HttpResponseBadRequest(
            '``limit`` param must be a positive number or 0!')
    limit = min(limit, SERVER_SIDE_SEARCH_LIMIT)
    if not is_number(page) or page < 0:
        return HttpResponseBadRequest(
            '``page`` param must be a positive number or 0!')

    # filter for requested model types
    model_list = [
        klass for klass, param_name in list(SEARCH_MODEL_NAMES.items())
        if params.get(param_name, False)
    ]
    sqs = SearchQuerySet().models(*model_list)
    # filter for map bounds (Points are constructed ith (lon, lat)!!!)
    if not params['ignore_location'] and not implicit_ignore_location:
        sqs = sqs.within('location', Point(params['sw_lon'], params['sw_lat']),
                         Point(params['ne_lon'], params['ne_lat']))
    # filter for user's own content
    if params['mine'] and request.user.is_authenticated:
        user_id = request.user.id
        sqs = sqs.filter_and(
            Q(creator=user_id) | Q(user_id=user_id) | Q(group_members=user_id))
    # filter for search terms
    if query:
        sqs = sqs.auto_query(query)
    # group-filtered-map view for on-group pages
    if filter_group_id:
        group = get_object_or_None(get_cosinnus_group_model(),
                                   id=filter_group_id)
        if group:
            filtered_groups = [filter_group_id]
            # get child projects of this group
            filtered_groups += [
                subproject.id for subproject in group.get_children()
                if subproject.is_active
            ]
            sqs = sqs.filter_and(
                Q(membership_groups__in=filtered_groups)
                | Q(group__in=filtered_groups))
    # filter topics
    topics = ensure_list_of_ints(params.get('topics', ''))
    if topics:
        sqs = sqs.filter_and(mt_topics__in=topics)
    # filter for portal visibility
    sqs = filter_searchqueryset_for_portal(
        sqs, restrict_multiportals_to_current=prefer_own_portal)
    # filter for read access by this user
    sqs = filter_searchqueryset_for_read_access(sqs, request.user)
    # filter events by upcoming status
    if params['events'] and Event is not None:
        sqs = filter_event_searchqueryset_by_upcoming(sqs)

    # filter all default user groups if the new dashboard is being used (they count as "on plattform" and aren't shown)
    if getattr(settings, 'COSINNUS_USE_V2_DASHBOARD', False):
        sqs = sqs.exclude(is_group_model=True,
                          slug__in=get_default_user_group_slugs())

    # if we hae no query-boosted results, use *only* our custom sorting (haystack's is very random)
    if not query:
        if prefer_own_portal:
            sqs = sqs.order_by('-portal', '-local_boost')
        else:
            sqs = sqs.order_by('-local_boost')

    # sort results into one list per model
    total_count = sqs.count()
    sqs = sqs[limit * page:limit * (page + 1)]
    results = []
    for result in sqs:
        # if we hae no query-boosted results, use *only* our custom sorting (haystack's is very random)
        if not query:
            result.score = result.local_boost
            if prefer_own_portal and is_number(result.portal) and int(
                    result.portal) == CosinnusPortal.get_current().id:
                result.score += 100.0
        results.append(HaystackMapResult(result, user=request.user))

    # if the requested item (direct select) is not in the queryset snippet
    # (might happen because of an old URL), then mix it in as first item and drop the last
    if item_id:
        item_id = str(item_id)
        if not any([res['id'] == item_id for res in results]):
            item_result = get_searchresult_by_itemid(item_id, request.user)
            if item_result:
                results = [HaystackMapResult(item_result, user=request.user)
                           ] + results[:-1]

    page_obj = None
    if results:
        page_obj = {
            'index': page,
            'count': len(results),
            'total_count': total_count,
            'start': (limit * page) + 1,
            'end': (limit * page) + len(results),
            'has_next': total_count > (limit * (page + 1)),
            'has_previous': page > 0,
        }

    data = {
        'results': results,
        'page': page_obj,
    }
    return JsonResponse(data)
Beispiel #5
0
 def convert(self, value):
     return ensure_list_of_ints(value)
Beispiel #6
0
def map_search_endpoint(request, filter_group_id=None):
    """ Maps API search endpoint using haystack search results. For parameters see ``MAP_SEARCH_PARAMETERS``
        returns JSON with the contents of type ``HaystackMapResult``
        
        @param filter_group_id: Will filter all items by group relation, where applicable 
                (i.e. users are filtered by group memberships for that group, events as events in that group)
    """
    implicit_ignore_location = not any([
        loc_param in request.GET
        for loc_param in ['sw_lon', 'sw_lat', 'ne_lon', 'ne_lat']
    ])
    params = _collect_parameters(request.GET, MAP_SEARCH_PARAMETERS)
    query = force_text(params['q'])
    limit = params['limit']
    page = params['page']
    item_id = params['item']

    if params.get('cloudfiles', False):
        return map_cloudfiles_endpoint(request, query, limit, page)

    # TODO: set to  params['external'] after the external switch button is in frontend!
    external = settings.COSINNUS_EXTERNAL_CONTENT_ENABLED

    prefer_own_portal = getattr(settings, 'MAP_API_HACKS_PREFER_OWN_PORTAL',
                                False)

    if not is_number(limit) or limit < 0:
        return HttpResponseBadRequest(
            '``limit`` param must be a positive number or 0!')
    limit = min(limit, SERVER_SIDE_SEARCH_LIMIT)
    if not is_number(page) or page < 0:
        return HttpResponseBadRequest(
            '``page`` param must be a positive number or 0!')

    # filter for requested model types
    model_list = [
        klass for klass, param_name in list(SEARCH_MODEL_NAMES.items())
        if params.get(param_name, False)
    ]

    sqs = SearchQuerySet().models(*model_list)

    # filter for map bounds (Points are constructed ith (lon, lat)!!!)
    if not params['ignore_location'] and not implicit_ignore_location:
        sqs = sqs.within('location', Point(params['sw_lon'], params['sw_lat']),
                         Point(params['ne_lon'], params['ne_lat']))
    # filter for user's own content
    if params['mine'] and request.user.is_authenticated:
        user_id = request.user.id
        sqs = sqs.filter_and(
            Q(creator=user_id) | Q(user_id=user_id) | Q(group_members=user_id))
    # filter for search terms
    if query:
        sqs = sqs.auto_query(query)

    # group-filtered-map view for on-group pages
    if filter_group_id:
        group = get_object_or_None(get_cosinnus_group_model(),
                                   id=filter_group_id)
        if group:
            filtered_groups = [filter_group_id]
            # get child projects of this group
            filtered_groups += [
                subproject.id for subproject in group.get_children()
                if subproject.is_active
            ]
            sqs = sqs.filter_and(
                Q(membership_groups__in=filtered_groups)
                | Q(group__in=filtered_groups))

    # filter topics
    topics = ensure_list_of_ints(params.get('topics', ''))
    if topics:
        sqs = sqs.filter_and(mt_topics__in=topics)
    if settings.COSINNUS_ENABLE_SDGS:
        sdgs = ensure_list_of_ints(params.get('sdgs', ''))
        if sdgs:
            sqs = sqs.filter_and(sdgs__in=sdgs)
    if settings.COSINNUS_MANAGED_TAGS_ENABLED:
        managed_tags = ensure_list_of_ints(params.get('managed_tags', ''))
        if managed_tags:
            sqs = sqs.filter_and(managed_tags__in=managed_tags)
    # filter for portal visibility
    sqs = filter_searchqueryset_for_portal(
        sqs,
        restrict_multiportals_to_current=prefer_own_portal,
        external=external)
    # filter for read access by this user
    sqs = filter_searchqueryset_for_read_access(sqs, request.user)
    # filter events by upcoming status and exclude hidden proxies
    if params['events'] and Event is not None:
        sqs = filter_event_searchqueryset_by_upcoming(sqs).exclude(
            is_hidden_group_proxy=True)

    # filter all default user groups if the new dashboard is being used (they count as "on plattform" and aren't shown)
    if getattr(settings, 'COSINNUS_USE_V2_DASHBOARD', False):
        sqs = sqs.exclude(is_group_model=True,
                          slug__in=get_default_user_group_slugs())

    # kip score sorting and only rely on natural ordering?
    skip_score_sorting = False
    # if we hae no query-boosted results, use *only* our custom sorting (haystack's is very random)
    if not query:
        sort_args = ['-local_boost']
        # if we only look at conferences, order them by their from_date, future first!
        if prefer_own_portal:
            sort_args = ['-portal'] + sort_args
        """
        # this would be the way to force-sort a content type by a natural ordering instead of score if its the only type being shown
        if params.get('conferences', False) and sum([1 if params.get(content_key, False) else 0 for content_key in MAP_CONTENT_TYPE_SEARCH_PARAMETERS.keys()]) == 1:
            sort_args = ['-from_date'] + sort_args
            skip_score_sorting = True
        sqs = sqs.order_by(*sort_args)
        """

    # sort results into one list per model
    total_count = sqs.count()
    sqs = sqs[limit * page:limit * (page + 1)]
    results = []

    for i, result in enumerate(sqs):
        if skip_score_sorting:
            # if we skip score sorting and only rely on the natural ordering, we make up fake high scores
            result.score = 100000 - (limit * page) - i
        elif not query:
            # if we hae no query-boosted results, use *only* our custom sorting (haystack's is very random)
            result.score = result.local_boost
            if prefer_own_portal and is_number(result.portal) and int(
                    result.portal) == CosinnusPortal.get_current().id:
                result.score += 100.0
        results.append(HaystackMapResult(result, user=request.user))

    # if the requested item (direct select) is not in the queryset snippet
    # (might happen because of an old URL), then mix it in as first item and drop the last
    if item_id:
        item_id = str(item_id)
        if not any([res['id'] == item_id for res in results]):
            item_result = get_searchresult_by_itemid(item_id, request.user)
            if item_result:
                results = [HaystackMapResult(item_result, user=request.user)
                           ] + results[:-1]

    page_obj = None
    if results:
        page_obj = {
            'index': page,
            'count': len(results),
            'total_count': total_count,
            'start': (limit * page) + 1,
            'end': (limit * page) + len(results),
            'has_next': total_count > (limit * (page + 1)),
            'has_previous': page > 0,
        }

    data = {
        'results': results,
        'page': page_obj,
    }
    return JsonResponse(data)