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)
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
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
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)
def convert(self, value): return ensure_list_of_ints(value)
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)